netty代理服务器事务

时间:2017-12-14 02:46:06

标签: java spring-boot proxy netty

我是netty的新手,我想使用netty创建一个代理服务器来执行以下操作:

_在从客户端接收数据后,代理服务器会执行一些可能修改数据的业务逻辑,然后将其转发到远程服务器,此业务逻辑属于事务。

_如果远程服务器返回成功响应,则代理服务器提交事务,否则代理服务器回滚事务。

Data flow diagram

我已经看过https://netty.io/4.1/xref/io/netty/example/proxy/package-summary.html的代理示例,但我还没有找到一种实现上述事务逻辑的简单方法。 我应该提一下,我已经创建了一个单独的线程池来执行这个业务事务以避免阻塞Nio线程,我当前的解决方案是实际使用具有相同线程数量的2个线程池:1在frontendHandler上,1在backendHandler上,前端的那个将使用wait()等待来自后端线程的响应。

这是我前端处理程序的当前代码:

$temp = $best_hot_lap->car->tyrestemperature;

和backendHandler:

@Override
public void channelActive(ChannelHandlerContext ctx) {
    final Channel inboundChannel = ctx.channel();

    // Start the connection attempt.
    Bootstrap b = new Bootstrap();
    b.group(inboundChannel.eventLoop())
        .channel(ctx.channel().getClass())
        .handler(new ServerBackendHandler(inboundChannel, response))
        .option(ChannelOption.AUTO_READ, false);
    ChannelFuture f = b.connect(remoteHost, remotePort);
    outboundChannel = f.channel();
    f.addListener(new ChannelFutureListener() {
        public void operationComplete(ChannelFuture future) throws Exception {
            if (future.isSuccess()) {
                // connection complete start to read first data
                inboundChannel.read();
            } else {
                // Close the connection if the connection attempt has failed.
                inboundChannel.close();
            }
        }
      });
  }

  @Override
  public void channelRead(final ChannelHandlerContext ctx, Object msg) {
      if (outboundChannel.isActive()) {

          //Executing business logic within a different thread pool to avoid blocking asynchronous i/o operation
          frontendThreadPool.execute(new Runnable(){

              @Override
              public void run() {
                  //System.out.println("Starting business logic operation at front_end for message :" + m);                     
                  synchronized(response) {

                      //sleeping this thread to simulate business operation, insert business logic here.
                      int randomNum = ThreadLocalRandom.current().nextInt(1000, 2001);
                      try {
                          Thread.currentThread().sleep(randomNum);

                      } catch (InterruptedException e1) {
                              e1.printStackTrace();

                      }

                      outboundChannel.writeAndFlush(msg).addListener(new ChannelFutureListener() {

                          public void operationComplete(ChannelFuture future) throws Exception {
                              if (future.isSuccess()) {
                                  // was able to flush out data, start to read the next chunk
                                  ctx.channel().read();

                              } else {
                                  future.channel().close();

                              }

                          }

                      });


                      System.out.println("Blank response : " + response.getResponse());

                          //wait for response from remote server  
                      try {
                          response.wait();

                      } catch (InterruptedException e) {
                          e.printStackTrace();

                      }

                      System.out.println("Returned response from back end: " + response.getResponse());

                      //another piece of business logic here, if the remote server returned success then commit the transaction, if the remote server returned failure then throw exception to rollback 

                      //stop current thread since we are done with it
                      Thread.currentThread().interrupt();                                                 
                  }

              }

          });

      }

  }

此解决方案根本没有优化,因为服务器必须使用2个线程来执行一个事务。所以我想我的问题是:

_我可以(如果可以,我应该)在channelRead方法上使用Spring @Transactional吗?

_如何使用netty以简单的方式实现上述逻辑?

我还使用JMeter来测试上面的代码,但它似乎不是很稳定,许多请求甚至没有响应上述代码在大约2000个连接和每个线程250个最大线程池

提前致谢

0 个答案:

没有答案