我是netty的新手,我想使用netty创建一个代理服务器来执行以下操作:
_在从客户端接收数据后,代理服务器会执行一些可能修改数据的业务逻辑,然后将其转发到远程服务器,此业务逻辑属于事务。
_如果远程服务器返回成功响应,则代理服务器提交事务,否则代理服务器回滚事务。
我已经看过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个最大线程池
提前致谢