SOA如何设计传输模块(二)-Netty的实现

上一遍介绍了设计传输模时接口的定义(http://blog.csdn.net/csujiangyu/article/details/51761479)

这里用了主流的框架netty来实现。

首先设计NettyServer,主要功能是绑定端口,监听连接。



public class NettyServer extends AbstractServer { private ServerBootstrap serverBootstrap; private EventLoopGroup bossGroup; private EventLoopGroup workerGroup; public NettyServer(ChannelHandler handler) { super(handler); } @Override public void bind(InetSocketAddress address) throws InterruptedException { bossGroup = new NioEventLoopGroup(); workerGroup = new NioEventLoopGroup(); serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { // (4) @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new DecoderHandler()); ch.pipeline().addLast(new NettyServerHandler(channelHandler)); ch.pipeline().addLast(new EncoderHandler()); } }) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); serverBootstrap.bind(address).sync(); } @Override public void close() { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } @Override public boolean isClosed() { return false; } }

这里为了简单,有些方法没有实现,比如isClosed,只是返回false。

NettyClient实现如下,主要是向服务端发起请求,建立连接。



public class NettyClient implements Client{ private Bootstrap bootstrap; private NioEventLoopGroup workerGroup; private ChannelHandler channelHandler; public NettyClient(ChannelHandler channelHandler){ this.channelHandler = channelHandler; init(); } private void init(){ workerGroup = new NioEventLoopGroup(); bootstrap = new Bootstrap(); bootstrap.group(workerGroup); // (2) bootstrap.channel(NioSocketChannel.class); // (3) bootstrap.option(ChannelOption.SO_KEEPALIVE, true); // (4) bootstrap.handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new DecoderHandler()); ch.pipeline().addLast(new NettyClientHandler(channelHandler)); ch.pipeline().addLast(new EncoderHandler()); } }); } @Override public Channel connect(InetSocketAddress inetSocketAddress) throws Exception { ChannelFuture f = bootstrap.connect(inetSocketAddress).sync(); io.netty.channel.Channel channel = f.channel(); return new NettyChannel(channel, channelHandler); } }

还需要实现Channel的实现


public class NettyChannel implements Channel {
    private static final ConcurrentHashMap<io.netty.channel.Channel, NettyChannel> channelMap = new ConcurrentHashMap<>();
    //包装netty的client,用到了适配器模式
    private io.netty.channel.Channel channel;
    private ChannelHandler channelHandler;
    public NettyChannel(io.netty.channel.Channel channel, ChannelHandler channelHandler) {
        this.channel = channel;
        this.channelHandler = channelHandler;
    }
    static NettyChannel getOrAddChannel(io.netty.channel.Channel channel, ChannelHandler handler) {
        NettyChannel ret = channelMap.get(channel);
        //不存在则尝试更新
        if (ret == null) {
            NettyChannel nettyChannel = new NettyChannel(channel, handler);
            //这里处于线程安全考虑,如果存在则更新,直接返回
            ret = channelMap.putIfAbsent(channel, nettyChannel);
            if (ret == null) {
                ret = nettyChannel;
            }
        }
        return ret;
    }
    static void removeIfInactive(io.netty.channel.Channel channel) {
        if (channel != null && !channel.isActive()) {
            channelMap.remove(channel);
        }
    }
    @Override
    public void send(Object message) {
        this.channel.writeAndFlush(message);
    }
    @Override
    public ChannelHandler getChannelHandler() {
        return channelHandler;
    }
    @Override
    public void close() {
    }
    @Override
    public boolean isClosed() {
        return false;
    }
    @Override
    public InetSocketAddress getRemoteAddress() {
        return null;
    }
    @Override
    public boolean isConnnect() {
        return false;
    }
}

然后是NettyServerHandler的实现


public class NettyServerHandler extends ChannelInboundHandlerAdapter {
    //消息转发到自定义可扩展的ChannelHandler
    private ChannelHandler channelHandler;
    public NettyServerHandler(ChannelHandler channelHandler){
        this.channelHandler = channelHandler;
    }
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        NettyChannel.getOrAddChannel(ctx.channel(), channelHandler);
    }
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object object) throws Exception {
        NettyChannel nettyChannel = NettyChannel.getOrAddChannel(ctx.channel(), channelHandler);
        channelHandler.receive(nettyChannel, object);
    }
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        NettyChannel.removeIfInactive(ctx.channel());
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

NettyClientHandler:


public class NettyClientHandler extends ChannelInboundHandlerAdapter {
    private ChannelHandler channelHandler;
    public NettyClientHandler(ChannelHandler channelHandler) {
        this.channelHandler = channelHandler;
    }
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        NettyChannel.getOrAddChannel(ctx.channel(), channelHandler);
    }
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object object) throws Exception {
        NettyChannel nettyChannel = NettyChannel.getOrAddChannel(ctx.channel(), channelHandler);
        channelHandler.receive(nettyChannel, object);
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

下面我们来验证一下,看能否满足SOA传输的需要。

定义服务提供者,用于暴露服务,这里的服务是HelloService


public class RpcProvider {
    private static final Map<String, Invoker> invokers = new ConcurrentHashMap<>();
    public static Invoker getInvoker(String className) {
        return invokers.get(className);
    }
    public static void export(String interfaceName, Class<?> clazz) {
        Invoker invoker = new ServerInvoker(clazz);
        invokers.put(interfaceName, invoker);
    }
    private static final ChannelHandler requestHandler = new AbstractChannelHandler() {
        @Override
        public void receive(Channel channel, Object object) throws Exception {
            if (object instanceof Request) {
                Request request = (Request) object;
                Invocation invocation = request.getInvocation();
                Invoker invoker = getInvoker(invocation.getClazz().getSimpleName());
                Result result = invoker.invoke(invocation);
                Response response = new Response();
                response.setMsgId(request.getMsgId());
                response.setResult(result.getData());
                send(channel, response);
            }
        }
    };
    public static void main(String[] args) throws Exception {
        Server server = new NettyServer(requestHandler);
        server.bind(new InetSocketAddress(Constant.LOCAL_HOST, Constant.PORT));
        export(HelloService.class.getSimpleName(), HelloServiceImpl.class);
    }
}

然后是定义消费者,发起RPC请求,引用远程服务HelloService


public class RpcConsumer {
    private static final ChannelHandler requestHandler = new AbstractChannelHandler() {
        @Override
        public void receive(Channel channel, Object message) throws Exception {
            if (message instanceof Response) {
                Response response = (Response) message;
                ResponseFuture future = ResponseFuture.getFuture(response.getMsgId());
                future.receive(response);
            }
        }
    };
    private static final Client client = new NettyClient(requestHandler);
    public static <T> T refer(final Class<T> clazz) throws Exception {
        final Channel channel = client.connect(new InetSocketAddress(Constant.LOCAL_HOST, Constant.PORT));
        ExchangeClient exchangeClient = new ExchangeClient();
        final ClientInvoker clientInvoker = new ClientInvoker(clazz);
        clientInvoker.setExchangeClient(exchangeClient);
        return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{clazz}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Invocation invocation = new Invocation();
                invocation.setClazz(clazz);
                invocation.setMethodName(method.getName());
                invocation.setParameterTypes(method.getParameterTypes());
                invocation.setArguments(args);
                Request request = new Request();
                request.setInvocation(invocation);
                ResponseFuture responseFuture = new ResponseFuture(request.getMsgId());
                channel.send(request);
                Response response = responseFuture.get();
                return response.getResult();
            }
        });
    }
    public static void main(String[] args) throws Exception {
        HelloService helloService = refer(HelloService.class);
        for (int i = 0; i < 100; i++) {
            String string = helloService.hello("Foo");
            System.out.println(string);
            Thread.sleep(1000);
        }
    }
}

分别启动上面两个程序,RpcConsumer控制台不断打印“Hello Foo”,说明调用成功。


Hello Foo
Hello Foo
Hello Foo
Hello Foo

源代码在https://github.com/Jdoing/example/tree/master/example-transport/src/main/java/example/transport/netty

和https://github.com/Jdoing/example/tree/master/example-soa/src/main/java/rpc3

你可能感兴趣的:(SOA)