completableFuture = new CompletableFuture<>();
77 | bootstrap.connect(inetSocketAddress).addListener((ChannelFutureListener) future -> {
78 | if (future.isSuccess()) {
79 | log.info("The client has connected [{}] successful!", inetSocketAddress.toString());
80 | completableFuture.complete(future.channel());
81 | } else {
82 | throw new IllegalStateException();
83 | }
84 | });
85 | return completableFuture.get();
86 | }
87 |
88 | public void close() {
89 | log.info("call close method");
90 | eventLoopGroup.shutdownGracefully();
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/lrpc-framework/src/main/java/com/cccll/remoting/transport/netty/client/NettyClientHandler.java:
--------------------------------------------------------------------------------
1 | package com.cccll.remoting.transport.netty.client;
2 |
3 | import com.cccll.enumeration.RpcMessageType;
4 | import com.cccll.factory.SingletonFactory;
5 | import com.cccll.remoting.dto.RpcRequest;
6 | import com.cccll.remoting.dto.RpcResponse;
7 | import io.netty.channel.*;
8 | import io.netty.handler.timeout.IdleState;
9 | import io.netty.handler.timeout.IdleStateEvent;
10 | import io.netty.util.ReferenceCountUtil;
11 | import lombok.extern.slf4j.Slf4j;
12 |
13 | import java.net.InetSocketAddress;
14 |
15 | /**
16 | * 自定义客户端ChannelHandler以处理服务器发送的数据
17 | *
18 | *
19 | * 如果继承自 SimpleChannelInboundHandler 的话就不要考虑 ByteBuf 的释放 ,{@link SimpleChannelInboundHandler} 内部的
20 | * channelRead 方法会替你释放 ByteBuf ,避免可能导致的内存泄露问题。详见《Netty进阶之路 跟着案例学 Netty》
21 | *
22 | * @author cccll
23 | * @createTime 2020年07月01日 22:18:00
24 | */
25 | @Slf4j
26 | public class NettyClientHandler extends ChannelInboundHandlerAdapter {
27 | private final UnprocessedRequests unprocessedRequests;
28 | private final ChannelProvider channelProvider;
29 |
30 | public NettyClientHandler() {
31 | this.unprocessedRequests = SingletonFactory.getInstance(UnprocessedRequests.class);
32 | this.channelProvider = SingletonFactory.getInstance(ChannelProvider.class);
33 | }
34 |
35 | /**
36 | * 利用Netty提供的高水位机制,对客户端做流控,避免netty发送队列积压发生OOM,
37 | * 当发送队列发送的字节数组到达高水位时,对应channel变为不可写状态,注意在此状态下调用write方法仍可将消息
38 | * 加入待发送队列,所以须在代码中对channel状态做判断
39 | *
40 | */
41 | @Override
42 | public void channelActive(ChannelHandlerContext ctx) {
43 | //此值须根据业务的QPS规划、客户端处理性能、网络带宽、链路数、消息平均码流大小等综合因素计算
44 | ctx.channel().config().setWriteBufferHighWaterMark(20*1024*1024);
45 | }
46 |
47 | /**
48 | * 读取从服务端返回的消息
49 | */
50 | @Override
51 | public void channelRead(ChannelHandlerContext ctx, Object msg) {
52 | try {
53 | log.info("client receive msg: [{}]", msg);
54 | if (msg instanceof RpcResponse) {
55 | RpcResponse