Skip to content

Commit 716e4ee

Browse files
committed
completed 从 Channel 引导的客户端
1 parent 57f343c commit 716e4ee

3 files changed

+83
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
从 Channel 引导的客户端
2+
====
3+
4+
有时你可能需要引导客户端 Channel 从另一个 Channel。这可能发生,如果您正在编写一个代理或从其他系统需要检索数据。后一种情况是常见的,因为许多 Netty 的应用程序集成现有系统,例如 web 服务或数据库。
5+
6+
你当然可以创建一个新的 Bootstrap 并使用它如9.2.1节所述,这个解决方案不一定有效。至少,你需要创建另一个 EventLoop 给新客户端 Channel 的,并且 Channel 将会需要在不同的 Thread 间进行上下文切换。
7+
8+
幸运的是,由于 EventLoop 继承自 EventLoopGroup ,您可以通过传递 接收到的 Channel 的 EventLoop 到 Bootstrap 的 group() 方法。这允许客户端 Channel 来操作 相同的 EventLoop,这样就能消除了额外的线程创建和所有相关的上下文切换的开销。
9+
10+
*为什么共享 EventLoop 呢?*
11+
12+
*当你分享一个 EventLoop ,你保证所有 Channel 分配给 EventLoop 将使用相同的线程,消除上下文切换和相关的开销。(请记住,一个EventLoop分配给一个线程执行操作。)*
13+
14+
共享一个 EventLoop 描述如下:
15+
16+
![](../images/Figure 9.4 EventLoop shared between channels with ServerBootstrap and Bootstrap.jpg)
17+
18+
1. 当 bind() 调用时,ServerBootstrap 创建一个新的ServerChannel 。 当绑定成功后,这个管道就能接收子管道了
19+
2. ServerChannel 接收新连接并且创建子管道来服务它们
20+
3. Channel 用于接收到的连接
21+
4. 管道自己创建了 Bootstrap,用于当 connect() 调用时创建一个新的管道
22+
5. 新管道连接到远端
23+
6. 在 EventLoop 接收通过 connect() 创建后就在管道间共享
24+
25+
Figure 9.4 EventLoop shared between channels with ServerBootstrap and Bootstrap
26+
27+
实现 EventLoop 共享,包括设置 EventLoop 引导通过Bootstrap.eventLoop() 方法。这是清单9.5所示。
28+
29+
ServerBootstrap bootstrap = new ServerBootstrap(); //1
30+
bootstrap.group(new NioEventLoopGroup(), //2
31+
new NioEventLoopGroup()).channel(NioServerSocketChannel.class) //3
32+
.childHandler( //4
33+
new SimpleChannelInboundHandler<ByteBuf>() {
34+
ChannelFuture connectFuture;
35+
36+
@Override
37+
public void channelActive(ChannelHandlerContext ctx) throws Exception {
38+
Bootstrap bootstrap = new Bootstrap();//5
39+
bootstrap.channel(NioSocketChannel.class) //6
40+
.handler(new SimpleChannelInboundHandler<ByteBuf>() { //7
41+
@Override
42+
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
43+
System.out.println("Reveived data");
44+
}
45+
});
46+
bootstrap.group(ctx.channel().eventLoop()); //8
47+
connectFuture = bootstrap.connect(new InetSocketAddress("www.manning.com", 80)); //9
48+
}
49+
50+
@Override
51+
protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {
52+
if (connectFuture.isDone()) {
53+
// do something with the data //10
54+
}
55+
}
56+
});
57+
ChannelFuture future = bootstrap.bind(new InetSocketAddress(8080)); //11
58+
future.addListener(new ChannelFutureListener() {
59+
@Override
60+
public void operationComplete(ChannelFuture channelFuture) throws Exception {
61+
if (channelFuture.isSuccess()) {
62+
System.out.println("Server bound");
63+
} else {
64+
System.err.println("Bound attempt failed");
65+
channelFuture.cause().printStackTrace();
66+
}
67+
}
68+
});
69+
70+
1. 创建一个新的 ServerBootstrap 来创建新的 SocketChannel 管道并且绑定他们
71+
2. 指定 EventLoopGroups 从 ServerChannel 和接收到的管道来注册并获取 EventLoops
72+
3. 指定 Channel 类来使用
73+
4. 设置处理器用于处理接收到的管道的 I/O 和数据
74+
5. 创建一个新的 Bootstrap 来连接到远程主机
75+
6. 设置管道类
76+
7. 设置处理器来处理 I/O
77+
8. 使用相同的 EventLoop 作为分配到接收的管道
78+
9. 连接到远端
79+
10. 连接完成处理业务逻辑 (比如, proxy)
80+
11. 通过配置了的 Bootstrap 来绑定到管道
81+
82+
注意,新的 EventLoop 会创建一个新的 Thread。出于该原因,EventLoop 实例应该尽量重用。或者限制实例的数量来避免耗尽系统资源。

SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ This is the summary of my book.
5959
* [Bootstrap 类型](CORE FUNCTIONS/Bootstrap types.md)
6060
* [引导客户端和无连接协议](CORE FUNCTIONS/Bootstrapping clients and connectionless protocols.md)
6161
* [引导服务器](CORE FUNCTIONS/Bootstrapping servers.md)
62+
* [从 Channel 引导的客户端](CORE FUNCTIONS/Bootstrapping clients from a Channel.md)
6263
* NETTY BY EXAMPLE
6364
* [单元测试](NETTY BY EXAMPLE/Unit Testing.md)
6465
* [WebSocket](NETTY BY EXAMPLE/WebSockets.md)
Loading

0 commit comments

Comments
 (0)