1 Transporter层概述
Transporter层位于第2层,已经实现了完整的TCP通信,定义了一套Dubbo自己的API接口,支持Netty、Mina等框架。
官方定义:
transport 网络传输层:抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 Channel, Transporter, Client, Server, Codec
个人理解:这里说的Message其实就是指java的任意对象(Object类)。
如:ChannelHandler类中的void sent(Channel channel, Object message) throws RemotingException;方法,负责接收一个对象。
如:Client类的void send(Object message, boolean sent) throws RemotingException;方法,负责发送一个对象。
通过查看Transporter扩展点,可以知道目前dubbo支持的TCP框架。
2 实践例子
2.1 项目结构
由于是TCP框架,所以有服务端和客户端,两端的代码。
服务端:
NettyTransporterServerTest类是服务端的执行入口
ServerChannelHandler类是一个回调了,当事件发生时,dubbo内部会回调相应的方法。类似Netty中的ChannelHandler。
客户端:
NettyTransporterClientTest类是客户端的执行入口
ClientChannelHandler类是一个回调了,当事件发生时,dubbo内部会回调相应的方法。类似Netty中的ChannelHandler。
2.2 服务端代码
NettyTransporterServerTest代码
Transporter接口是核心类,通过调用bind方法可以在指定端口上监听,等待客户端连接。
URL用来指定ip和端口。
package org.example.dubbo.transport;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.URLBuilder;
import org.apache.dubbo.remoting.ChannelHandler;
import org.apache.dubbo.remoting.RemotingException;
import org.apache.dubbo.remoting.RemotingServer;
import org.apache.dubbo.remoting.Transporter;
import org.apache.dubbo.remoting.transport.netty4.NettyTransporter;
import java.io.IOException;
/** 启动netty 服务器 . 使用命令行 netstat -ano | findstr 8888 查看端口是否监听*/
public class NettyTransporterServerTest {
public static void main(String[] args) throws RemotingException, IOException {
Transporter transporter = new NettyTransporter();
ChannelHandler channelHandler = new ServerChannelHandler();
URLBuilder urlBuilder = new URLBuilder();
urlBuilder.setHost("localhost");
urlBuilder.setPort(8888);
URL url = urlBuilder.build();
RemotingServer remotingServer = transporter.bind(url, channelHandler);
System.in.read();
}
}
ServerChannelHandler代码
该类完成具体的出逻辑,目前为了方便调试都是打印了基本日志信息。
package org.example.dubbo.transport;
import org.apache.dubbo.remoting.Channel;
import org.apache.dubbo.remoting.ChannelHandler;
import org.apache.dubbo.remoting.RemotingException;
public class ServerChannelHandler implements ChannelHandler{
@Override
public void connected(Channel channel) throws RemotingException {
System.out.println("server-XXX connected");
}
@Override
public void disconnected(Channel channel) throws RemotingException {
System.out.println("server-XXX disconnected");
}
@Override
public void sent(Channel channel, Object message) throws RemotingException {
System.out.println("server-XXX sent="+message);
}
@Override
public void received(Channel channel, Object message) throws RemotingException {
System.out.println("server-XXX received=" + message);
}
@Override
public void caught(Channel channel, Throwable exception) throws RemotingException {
System.out.println("server-XXX caught");
exception.printStackTrace();
}
}
2.3 客户端代码
NettyTransporterClientTest代码
Transporter接口是核心类,通过调用connect方法连接到指定的服务端。
URL用来指定ip和端口。
连接完成后,客户端调用了client.send("abc", true) 来发送了一条信息。
package org.example.dubbo.transport;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.URLBuilder;
import org.apache.dubbo.remoting.ChannelHandler;
import org.apache.dubbo.remoting.Client;
import org.apache.dubbo.remoting.RemotingException;
import org.apache.dubbo.remoting.Transporter;
import org.apache.dubbo.remoting.transport.netty4.NettyTransporter;
public class NettyTransporterClientTest {
public static void main(String[] args) throws RemotingException {
Transporter transporter = new NettyTransporter();
ChannelHandler channelHandler = new ClientChannelHandler();
URLBuilder urlBuilder = new URLBuilder();
urlBuilder.setHost("localhost");
urlBuilder.setPort(8888);
URL url = urlBuilder.build();
Client client = transporter.connect(url, channelHandler);
client.send("abc", true);
client.close();
}
}
ClientChannelHandler代码
package org.example.dubbo.transport;
import org.apache.dubbo.remoting.Channel;
import org.apache.dubbo.remoting.ChannelHandler;
import org.apache.dubbo.remoting.RemotingException;
public class ClientChannelHandler implements ChannelHandler{
@Override
public void connected(Channel channel) throws RemotingException {
System.out.println("Client-XXX connected");
}
@Override
public void disconnected(Channel channel) throws RemotingException {
System.out.println("Client-XXX disconnected");
}
@Override
public void sent(Channel channel, Object message) throws RemotingException {
System.out.println("Client-XXX sent="+message);
}
@Override
public void received(Channel channel, Object message) throws RemotingException {
System.out.println("Client-XXX received=" + message);
}
@Override
public void caught(Channel channel, Throwable exception) throws RemotingException {
System.out.println("Client-XXX caught");
exception.printStackTrace();
}
}
2.4 执行结果
2.4.1 启动Server端
通过netstat -ano | findstr 8888 命令查看一下是否启动成功。
启动客户端后,可以在服务端看到日志
server-XXX connected : 表示客户端已经连接成功。
server-XXX received=abc :表示服务端已经接收到了abc数据。
server-XXX caught : 因为客户端发送完数据就关闭了,所以执行了caugth方法。
server-XXX disconnected:服务端关闭了连接。
2.4.2 启动客户端
Client-XXX connected : 客户端连接服务端成功。
Client-XXX sent=abc :发送了abc数据。
2.5 总结
通过dubbo的封装,几行代码就可以实现服务端和客户端的代码,并且可以随时切换Netty、Mina等通用框架。