proxyee icon indicating copy to clipboard operation
proxyee copied to clipboard

可不可以重用eventloopgroup?

Open Babagilo opened this issue 7 years ago • 5 comments

我把您的 run()method 稍加修改了一下,特别是现在只用了2个EventLoopGroup。 这是从《Netty In Action》这本书里受到的启发:

Suppose your server is processing a client request that requires it to act as a client to a third system. This can happen when an application, such as a proxy server, has to integrate with an organization’s existing systems, such as web services or databases. In such cases you’ll need to bootstrap a client Channel from a ServerChannel. You could create a new Bootstrap as described in section 8.2.1, but this is not the most efficient solution, as it would require you to define another EventLoop for the new client Channel. This would produce additional threads, necessitating context switching when exchanging data between the accepted Channel and the client Channel. A better solution is to share the EventLoop of the accepted Channel by passing it to the group() method of the Bootstrap. Because all Channels assigned to an EventLoop use the same thread, this avoids the extra thread creation and related context-switching mentioned previously.

================== 您觉得这样改合适吗? -- Babagilo

public void run(int port) throws InterruptedException, CertificateException, InvalidKeySpecException,
		NoSuchAlgorithmException, NoSuchProviderException, IOException {
	bossGroup = new NioEventLoopGroup(1);
	workerGroup = new NioEventLoopGroup();

	try {
		ServerBootstrap b = new ServerBootstrap();
		b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 100)
				//.handler(new LoggingHandler(LogLevel.INFO))
				.childHandler(new ChannelInitializer<SocketChannel>() {

					@Override
					protected void initChannel(SocketChannel ch) throws Exception {
						BabagiloProxyHandler serverHandler = proxyMode == ProxyMode.TUNNEL
								? new BabagiloProxyHandler(ch.eventLoop())
								: new BabagiloProxyHandler(ch.eventLoop(), proxyInterceptInitializer,
										proxyConfig, httpProxyExceptionHandle,  serverPrivateKey,  issuer,  ca_private_key,
										 caNotBefore,  caNotAfter,  serverPubKey);

						ch.pipeline().addLast("httpCodec", new HttpServerCodec());
						ch.pipeline().addLast("serverHandle", serverHandler);
					}
				});
		// Start the server
		ChannelFuture f = b.bind(port).sync();
		// Wait until the server socket is closed
		//System.err.format("BabagiloProxy is listening at localhost:%d; Mode: %s%n", port, this.proxyMode);
		f.channel().closeFuture().sync();
		
	} finally {
		bossGroup.shutdownGracefully();
		workerGroup.shutdownGracefully();
	}
}

Babagilo avatar Dec 03 '18 10:12 Babagilo

已经重用了呀,你指的是哪里要重用

monkeyWie avatar Dec 05 '18 01:12 monkeyWie

你除了bossGroup 和 workerGroup之外,还有第三个eventLoopGroup,是在 serverConfig.setProxyLoopGroup(new NioEventLoopGroup(serverConfig.getProxyGroupThreads())); 这一行被instantiated。

我的重构后的code里,没有用到这第三个eventLoopGroup,而是用 new BabagiloProxyHandler(ch.eventLoop())。。。。 将assign给client <-- > proxy 通道的eventLoop 传给了后面的 proxy <-->origin 通道来共用

谢谢, Babagilo

Babagilo avatar Dec 05 '18 01:12 Babagilo

这个我之前也是这样复用的,后来不记得是碰到个什么问题才把proxy的eventLoop独立出来使用。。

monkeyWie avatar Dec 05 '18 07:12 monkeyWie

这样子我就不知道该不该改了。。。

Babagilo avatar Dec 05 '18 10:12 Babagilo

可能是我之前proxy connect->origin 用的同步写法,导致connect阻塞的时候线程被占用后续的客户端连接就全被阻塞住了,后来改成异步写法应该就不会有这个问题,代码是这部分:

cf = bootstrap.connect(host, port);
      cf.addListener((ChannelFutureListener) future -> {
        if (future.isSuccess()) {
          future.channel().writeAndFlush(msg);
          synchronized (requestList) {
            requestList.forEach(obj -> future.channel().writeAndFlush(obj));
            requestList.clear();
            isConnect = true;
          }
        } else {
          requestList.forEach(obj -> ReferenceCountUtil.release(obj));
          requestList.clear();
          future.channel().close();
          channel.close();
        }

monkeyWie avatar Dec 06 '18 01:12 monkeyWie