netty worker线程释放 对channel是单线程么

966,690 八月 独立访问用户
语言 & 开发
架构 & 设计
文化 & 方法
您目前处于:
Netty系列之Netty并发编程分析
Netty系列之Netty并发编程分析
Author Contacted
相关厂商内容
相关赞助商
更多AWS最新精彩内容和活动,!
告诉我们您的想法
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
Re: volatile的特性描述问题
关于 Volatile 那段代码
我们预期程序会在3S后停止
Re: 关于 Volatile 那段代码
Re: 关于 Volatile 那段代码
Re: 关于 Volatile 那段代码
Re: 关于 Volatile 那段代码
Re: 关于 Volatile 那段代码
Re: 关于 Volatile 那段代码
Re: 关于 Volatile 那段代码
Re: 关于 Volatile 那段代码
好文章,讲解的通俗易懂
Re: 关于 Volatile 那段代码
Re: 好文章,讲解的通俗易懂
Re: 关于 Volatile 那段代码
timer timer
Re: 关于 Volatile 那段代码
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
赞助商链接
InfoQ每周精要
通过个性化定制的新闻邮件、RSS Feeds和InfoQ业界邮件通知,保持您对感兴趣的社区内容的时刻关注。
架构 & 设计
文化 & 方法
<及所有内容,版权所有 &#169;
C4Media Inc.
服务器由 提供, 我们最信赖的ISP伙伴。
北京创新网媒广告有限公司
京ICP备号-7
注意:如果要修改您的邮箱,我们将会发送确认邮件到您原来的邮箱。
使用现有的公司名称
修改公司名称为:
公司性质:
使用现有的公司性质
修改公司性质为:
使用现有的公司规模
修改公司规模为:
使用现在的国家
使用现在的省份
Subscribe to our newsletter?
Subscribe to our industry email notices?
We notice you’re using an ad blocker
We understand why you use ad blockers. However to keep InfoQ free we need your support. InfoQ will not provide your data to third parties without individual opt-in consent. We only work with advertisers relevant to our readers. Please consider whitelisting us.netty解析Post的键值对
解析时必须加上一个方法,ch.pipeline().addLast(new HttpObjectAggregator(2048)); 放在自己的Handel前面。
http服务器把HttpObjectAggregator放入管道里。HttpObjectAggregator会把多个消息转换为一个单一的FullHttpRequest或是FullHttpResponse。
To solve the problem you either need to&offer()&all chunks (HttpContent) of a message to&HttpPostRequestDecoder&before calling&getBodyHttpDatas(), or alternatively you can just add the&HttpObjectAggregator&handler right before your handler to the channel's pipeline. If you do so,&HttpObjectAggregator&will collect all chunks for you and produce a single&FullHttpRequest&in place of multiple chunks. Passing&FullHttpRequest&instead of an ordinary&HttpRequest&to&HttpPostRequestDecoder's constructor eliminates need to&offer()&chunks.
So you just need to&pipeline.addLast(new HttpObjectAggregator(1048576))&before adding your handler. For example:
public class YourServerInitializer extends ChannelInitializer&SocketChannel& {
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new HttpObjectAggregator(1048576));
pipeline.addLast(new YourServerHandler());
一,服务端的编码。
* Created with IntelliJ IDEA.
* User: xiaoyongyong
public class HttpServer implements Runnable{
private final static org.slf4j.Logger LOG = LoggerFactory.getLogger(HttpServer.class);
private final int
private volatile boolean closed = false;
private volatile EventLoopGroup bossG
private volatile EventLoopGroup workerG
private volatile ServerB
public HttpServer(int port) {
this.port =
public void init() {
closed = false;
//配置服务端的NIO线程组
bossGroup = new NioEventLoopGroup();
workerGroup = new NioEventLoopGroup();
bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup);
bootstrap.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer&SocketChannel&() {
public void initChannel(SocketChannel ch) throws Exception {
// server端发送的是httpResponse,所以要使用HttpResponseEncoder进行编码
ch.pipeline().addLast(new HttpResponseEncoder());
// server端接收到的是httpRequest,所以要使用HttpRequestDecoder进行解码
ch.pipeline().addLast(new HttpRequestDecoder());
// 把多个消息转换为一个单一的FullHttpRequest或是FullHttpResponse,解决Post请求参数解析
ch.pipeline().addLast(new HttpObjectAggregator(2048));
ch.pipeline().addLast(new HttpServerHandler());
}).option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
public void bind() throws Exception{
if (isClosed()) {
//绑定端口,开始绑定server,通过调用sync同步方法阻塞直到绑定成功
ChannelFuture channelFuture = bootstrap.bind(port).sync();
System.out.println("HTTP服务器启动成功,端口号:" + port);
//应用程序会一直等待,直到channel关闭
channelFuture.channel().closeFuture().sync();
System.out.println("服务器退出完毕,端口号:" + port);
public void close() {
closed = true;
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
System.out.println("关闭http服务器: " + port);
public void run() {
HttpServer server = new HttpServer(port);
server.init();
while (true) {
server.bind();
}catch (Exception e){
LOG.error("",e);
e.printStackTrace();
}finally {
server.close();
Thread.sleep(2000);
} catch (Exception e) {
LOG.error("",e);
e.printStackTrace();
public boolean isClosed() {
二,自己定义的处理类。
* Created on .
* http请求处理类r
* @author : xiaoyongyong
public class HttpServerHandler extends ChannelHandlerAdapter {
private static final Log LOG = LogFactory.getLog(HttpServerHandler.class);
private static ScheduledExecutorService executor = null;
private static volatile BlockingQueue&QueueBean& queue = null;
private static volatile String serverIp = null;
executor = Executors.newScheduledThreadPool(Integer.valueOf(PropertiesUtil.readValue(Constants.SERVER_THREAD_POOL)));
queue = new ArrayBlockingQueue&&(Integer.valueOf(PropertiesUtil.readValue(Constants.SERVER_QUEUE_CAPACITY)));
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (serverIp == null) {
serverIp = ((InetSocketAddress) ctx.channel().localAddress()).getAddress().getHostAddress();
queue.put(new QueueBean(ctx, msg));
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
LOG.error("ctx close!",cause);
ctx.close();
class QueueBean {
private final ChannelHandlerC
private final O
QueueBean(ChannelHandlerContext ctx, Object msg) {
this.ctx =
this.msg =
public ChannelHandlerContext getCtx() {
public Object getMsg() {
Thread thread = new Thread(new ChannelReadScan(),"ServerChannelReadScan");
thread.setDaemon(true);
thread.start();
private static class ChannelReadScan implements Runnable {
public void run() {
while (true) {
final QueueBean queueBean = queue.take();
executor.execute(new Runnable() {
public void run() {
ChannelHandlerContext ctx = queueBean.getCtx();
Object msg = queueBean.getMsg();
if (msg instanceof HttpRequest) {
HttpRequest req = (HttpRequest)
if (HttpHeaders.is100ContinueExpected(req)) {
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.CONTINUE));
boolean keepAlive = HttpHeaders.isKeepAlive(req);
// 解析http头部
for (Map.Entry&String, String& h : req.headers()) {
LOG.debug("HEADER: " + h.getKey() + " = " + h.getValue());
String uri = req.getUri();
LOG.debug("uri:" + uri);
if (uri.endsWith("/favicon.ico")) {
if (uri.startsWith("http")) {
uri = uri.replaceAll("http://[^/]+","");
String requestPath = uri.trim().split("\\?")[0];
Map&String, String& params = convertToMap(uri,req);
Object result = service(requestPath, params,req,ctx);
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(JSON.toJSONString(result).getBytes()));
response.headers().set(CONTENT_TYPE, "text/ charset=UTF-8");
response.headers().set(CONTENT_LENGTH, response.content().readableBytes());
if (!keepAlive) {
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
response.headers().set(CONNECTION, Values.KEEP_ALIVE);
ctx.writeAndFlush(response);
}catch (Exception e){
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
private Map&String, String& convertToMap(String uri,HttpRequest req) {
Map&String, String& params = new HashMap&&();
// 是GET请求
if (HttpMethod.GET.equals(req.getMethod())) {
// 解析请求参数
QueryStringDecoder queryStringDecoder = new QueryStringDecoder(uri);
Map&String, List&String&& paramMap = queryStringDecoder.parameters();
for (Map.Entry&String, List&String&& entry : paramMap.entrySet()) {
params.put(entry.getKey(), entry.getValue().get(0));
if (HttpMethod.POST.equals(req.getMethod())) {
// 是POST请求
HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(new DefaultHttpDataFactory(false), req);
List&InterfaceHttpData& postList = decoder.getBodyHttpDatas();
for (InterfaceHttpData data : postList) {
if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
MemoryAttribute attribute = (MemoryAttribute)
params.put(attribute.getName(), attribute.getValue());
private Object service(String requestPath, Map&String,String& params,HttpRequest req,ChannelHandlerContext ctx) {
long startTime = System.currentTimeMillis();
result = Dispatcher.service(requestPath, params);
long spentTime = System.currentTimeMillis() - startT
log(requestPath, req, ctx, (List&SyncMonitor&) result, spentTime);
} catch (Exception e) {
e.printStackTrace();
result = SyncMonitor.createExceptionResult("服务器异常:" + e.getCause().getMessage());
private void log(String requestPath, HttpRequest req, ChannelHandlerContext ctx,List&SyncMonitor& result, long spentTime) {
for(SyncMonitor syncMonitor: result){
LogBean logBean = new LogBean();
logBean.setAction(requestPath);
logBean.setIn_param(requestPath);
logBean.setC_ip(getClientIp(req, ctx));
logBean.setS_ip(serverIp);
int status = (syncMonitor.getStatus());
if (status == SyncMonitor.STATUS_EXCEPTION) {
logBean.setError_msg(JSON.toJSONString(syncMonitor.getMessage()));
logBean.setError_no(status + "");
logBean.setResult(status + "");
logBean.setSpent_time(spentTime + "");
logBean.setLog_type("info");
logBean.setSys_no("trade_data_monitor");
(logBean);
private String getClientIp(HttpRequest req,ChannelHandlerContext ctx) {
String clientIP = req.headers().get("X-Forwarded-For");
if (clientIP == null) {
InetSocketAddress insocket = (InetSocketAddress) ctx.channel()
.remoteAddress();
clientIP = insocket.getAddress().getHostAddress();
return clientIP;
三,客户端请求。
* Created on .
xiaoyongyong
public class HttpClientUtil {
public static final String METHOD_POST = "post";
public static final String METHOD_GET = "get";
public static CloseableHttpC
public static
CloseableHttpClient getHttpClient() {
if (httpclient == null) {
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
// Configure total max or per route limits for persistent connections
// that can be kept in the pool or leased by the connection manager.
connManager.setMaxTotal(100);
connManager.setDefaultMaxPerRoute(10);
httpclient = HttpClients.custom().setConnectionManager(connManager).build();
* 发送请求
* @throws Exception
public static byte[] sendRequest(String url,String methodType,boolean isDataBack) throws Exception {
CloseableHttpClient httpclient = getHttpClient();//HttpClients.createDefault();
HttpResponse response = null;
HttpUriRequest httpRequest = null;
byte[] data = null;
url = URLEncoder.encode(url, "UTF-8");
if (METHOD_GET.equals(methodType)) {
httpRequest = new HttpPost(url);
} else if (METHOD_POST.equals(methodType)) {
httpRequest = new HttpGet(url);
System.out.println("Executing request " + httpRequest.getRequestLine());
// Create a custom response handler
ResponseHandler&String& responseHandler = new ResponseHandler&String&() {
public String handleResponse(
final HttpResponse response) throws IOException {
int status = response.getStatusLine().getStatusCode();
System.out.println(status + ":" + response.getStatusLine().getReasonPhrase());
if (status &= 200 && status & 300) {
HttpEntity entity = response.getEntity();
return entity != null ? EntityUtils.toString(entity) : null;
throw new ClientProtocolException("Unexpected response status: " + status);
if (isDataBack) {
data = parseHttpEntity(response.getEntity());
String responseBody = httpclient.execute(httpRequest, responseHandler);
System.out.println("responseBody:"+responseBody);
} finally {
if (response != null) {
EntityUtils.consume(response.getEntity());
httpclient.close();
* 解析httpEntity
* @throws Exception
public static byte[] parseHttpEntity(HttpEntity entity) throws Exception {
try (InputStream in = entity.getContent()) {
return IOUtils.toByteArray(in);
* Post传递键值对参数
public static String sendPostRequest(String url, Map&String, String& param) throws Exception{
List&BasicNameValuePair& params = new ArrayList&&();
for (Map.Entry&String ,String& entry :param.entrySet()){
params.add(new BasicNameValuePair(entry.getKey(),entry.getValue()));
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(params));
return sendPostRequest(httpPost);
* 发送请求
public static String sendPostRequest(HttpUriRequest httpRequest) throws Exception {
CloseableHttpClient httpClient = getHttpClient();//HttpClients.createDefault();
HttpResponse response = null;
String responseBody = "";
ResponseHandler&String& responseHandler = new ResponseHandler&String&() {
public String handleResponse(final HttpResponse response) throws IOException {
int status = response.getStatusLine().getStatusCode();
if (status &= 200 && status & 300) {
HttpEntity entity = response.getEntity();
return entity != null ? EntityUtils.toString(entity) : null;
throw new ClientProtocolException("Unexpected response status: " + status);
responseBody = httpClient.execute(httpRequest, responseHandler);
}catch (Exception e){
e.printStackTrace();
}finally {
if (response != null) {
EntityUtils.consume(response.getEntity());
return responseB
阅读(...) 评论()Netty大并发时出现解码错误
[问题点数:40分,结帖人meoujb]
Netty大并发时出现解码错误
[问题点数:40分,结帖人meoujb]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2012年8月 总版技术专家分月排行榜第三2012年7月 总版技术专家分月排行榜第三
2014年8月 高性能开发大版内专家分月排行榜第一2013年11月 高性能开发大版内专家分月排行榜第一2012年12月 Java大版内专家分月排行榜第一2012年11月 Java大版内专家分月排行榜第一2012年10月 Java大版内专家分月排行榜第一2012年9月 Java大版内专家分月排行榜第一2012年8月 Java大版内专家分月排行榜第一2012年7月 Java大版内专家分月排行榜第一2012年6月 Java大版内专家分月排行榜第一2012年5月 Java大版内专家分月排行榜第一2012年4月 Java大版内专家分月排行榜第一2012年3月 Java大版内专家分月排行榜第一2012年2月 Java大版内专家分月排行榜第一2012年1月 Java大版内专家分月排行榜第一
本帖子已过去太久远了,不再提供回复功能。Netty的Reactor线程组中的每个Reactor线程处理网络I/O为什么一定要串行化,并行化不是更能提高系统吞吐量吗?
&img data-rawheight=&262& data-rawwidth=&610& src=&/afbb719b4dffe536d64895_b.jpg& class=&origin_image zh-lightbox-thumb& width=&610& data-original=&/afbb719b4dffe536d64895_r.jpg&&上图是一个Reactor线程模型,基于select(),epoll(),Reactor线程将I/O调用请求和I/O操作分离开,理论上一个Reactor线程能处理N个网络I/O操作,但是当并发量很大的时候,一个Reactor线程就会出现响应缓慢,连接超时等问题。&br&============================================================&br&那么一个Reactor线程模型应付不了大并发的网络请求,我们就可以更进一步选择Reactor线程组,一下是netty的主从Reactor线程组模型:&br&&img data-rawheight=&419& data-rawwidth=&694& src=&/6d86f75a0fb74_b.jpg& class=&origin_image zh-lightbox-thumb& width=&694& data-original=&/6d86f75a0fb74_r.jpg&&Reactor线程组实现了多个Reactor线程并行处理网络I/O,但是一个Reactor线程在同一时刻只能处理一个网络I/O(netty中是这么选择的)&br&&img data-rawheight=&283& data-rawwidth=&613& src=&/2a0d420a746f0bb625f2f5daa717c44c_b.jpg& class=&origin_image zh-lightbox-thumb& width=&613& data-original=&/2a0d420a746f0bb625f2f5daa717c44c_r.jpg&&&br&有问题要请教了,Reactor线程能将网络I/O调用请求和I/O操作分离开来,那么我们完全可以将I/O操作封装成一个TASK交给自定义的线程池去执行啊,这样的话不就加大了程序的并行化,提高了系统的吞吐量吗?(虽然它带来了线程上下文切换的开销)&br&&br&-----------将Reactor线程组中的单个Reactor线程模型该成一下这样:&br&&img data-rawheight=&321& data-rawwidth=&512& src=&/c0cf78b522f4fb6d85b6be4_b.jpg& class=&origin_image zh-lightbox-thumb& width=&512& data-original=&/c0cf78b522f4fb6d85b6be4_r.jpg&&
上图是一个Reactor线程模型,基于select(),epoll(),Reactor线程将I/O调用请求和I/O操作分离开,理论上一个Reactor线程能处理N个网络I/O操作,但是当并发量很大的时候,一个Reactor线程就会出现响应缓慢,连接超时等问题。============================================================那么一个Reactor线程模型应付不了大并发的网络请求,我们就可以更进一步选择Reactor线程组,一下是netty的主从Reactor线程组模型:…
使用NIO就意味着在处理IO过程中不会发生无意义的阻塞 也就不需要为了"阻塞需求"启动超过实际处理能力的线程数 这样减少了无意义的切换这里的串行不是指等待一个"业务上的请求"完成后再继续处理下一个请求 而是:选择器返回可读套接字(1) -& 接受数据(2) -& 按照业务需求encode -& 是否完成 -& 是 -& 委托业务处理线程 -& 退回到步骤1
-& 否 -& 指定套接字是否有剩余的内容 -& 否 -& 退回到步骤1
是 -& 返回到步骤2
我也有题主相同的疑问。借用Doug Lea大叔的一张图网络服务器的基本功能就是建立连接,读取请求,解析请求,调用处理过程,编码结果,发送结果。网络服务器的基本功能就是建立连接,读取请求,解析请求,调用处理过程,编码结果,发送结果。下面部分截图来源于网络Netty是典型的Reactor模型结构,下面说明一下Reactor模型的经典编程结构单线程,即只有一个selector来接受建立连接请求,读取数据,处理请求,返回数据。单线程,即只有一个selector来接受建立连接请求,读取数据,处理请求,返回数据。采用了多线程,虽然仍旧是单个selector线程,但是请求的处理大头交给了线程池异步执行。采用了多线程,虽然仍旧是单个selector线程,但是请求的处理大头交给了线程池异步执行。事实上,大部分网络程序为了更高的性能,都采用了多个Selector线程,即Reactor线程组的模型,Netty也不例外,采用了多个Selector。------------------------------------------------------------------------------------------------------------------------这张图近似于Netty的Reactor模型,唯一不同的是Netty并没有ThreadPool来异步的处理请求,而是串行的处理请求,这张图近似于Netty的Reactor模型,唯一不同的是Netty并没有ThreadPool来异步的处理请求,而是串行的处理请求,合适了。合适了。-------------------------------------------------------------------------------------------------------------我司(游戏服务器)采用的就是第二种Reactor模型,默认启用了4个Selector。同时将请求的解析和请求的处理独立出了两个线程池(不过现在看来每个线程池都是惊人的100个线程有点不安)selector线程将数据获取之后(自然是byte[]类型),丢给请求解析线程池去分发,分发到请求处理线程池当中。附带说一句,我上家单位(也是游戏公司)使用Netty做网络通信框架,就是使用Reactor同步处理请求和IO。虽然都使用过两种模型,但是毕竟游戏类型不同,数据库完全不同(一个mysql 一个自研nosql 还是java封装的nosql,nio也是自己封装的)所以很难比较例外采用异步的处理时在游戏服务器场景中可能出现:两个请求同时到达被处理,这是不能被允许的,因此需要确保处理完这个人第一个请求之后再处理下一个请求。-----------------------------------------------------------------------------------------------------------------由于采用了异步并行的处理方式,所以在返回数据的时候需要指明是哪个Channel的数据,需要保存上下文。--------------------------------正如上面各位大牛所说,线程切换和保存上下文的开销也是很大的,但是不足以使内存爆掉 具体怎么选取应用场景还请各位并发编程大牛解读。------------------------------------------目前看来,只是使用netty这种同步的处理方式是不妥的,使用mysql的数据库很有可能造成逻辑处理的耗时操作。下面的操作是可行的。Netty是事件驱动的,可以通过ChannelHandler链来控制执行流向。因为ChannelHandler链的执行过程是在subReactor中同步的,所以如果业务处理handler耗时长,将严重影响可支持的并发数。这种模型适合这种模型适合于像 Memcache 这 样的应用场景, 但 对需要操作数据库或者和其他模块阻塞交互的系统就不是很 合适。 但是Netty 的可扩展性非常好, 而像 ChannelHandler 线程池化的需要, 可以 通过在ChannelPipeline 中添加 Netty 内置的 ChannelHandler 实现类 –ExecutionHandler 实现, 对使用者来说只是 添加一行代码而已。 对于 ExecutionHandler 需要的线程池模型, Netty 提供了两种可 选: 1) MemoryAwareThreadPoolExecutor 可控制 Executor 中待处理任务的上限( 超过 上限时, 后续进来的任务将被阻 塞) , 并可控制单个 Channel 待处理任务的上 限; 2) OrderedMemoryAwareThreadPoolExecutor 是 MemoryAwareThreadPoolExecutor 的子类, 它还可以保证同一 Channel 中处 理的事件流的顺序性, 这主要是控制事件在异步处 理模式下可能出现的错误的 事件顺序, 但它并不保证同一 Channel 中的事件都在一个线程中执行( 通常也没 必要) 。 一般来 说, OrderedMemoryAwareThreadPoolExecutor 是个很不错的选 , 也可以 DIY 一个。下面的参考资料2.4. Netty线程开发最佳实践 2.4.1. 时间可控的简单业务直接在IO线程上处理
如果业务非常简单,执行时间非常短,不需要与外部网元交互、访问数据库和磁盘,不需要等待其它资源,则建议直接在业务ChannelHandler中执行,不需要再启业务的线程或者线程池。避免线程上下文切换,也不存在线程并发问题。
2.4.2. 复杂和时间不可控业务建议投递到后端业务线程池统一处理
对于此类业务,不建议直接在业务ChannelHandler中启动线程或者线程池处理,建议将不同的业务统一封装成Task,统一投递到后端的业务线程池中进行处理。过多的业务ChannelHandler会带来开发效率和可维护性问题,不要把Netty当作业务容器,对于大多数复杂的业务产品,仍然需要集成或者开发自己的业务容器,做好和Netty的架构分层。这个问题也可以参考
现在服务器一般是多核,服务器应该要利用多核,多核的时候,线程数核数接近能最大化性能,不然线程切换有损耗。所以服务器设计一般是一个主线程accept得到fd之后分发到其他线程,其他线程做epoll处理I/O, 这些处理I/O的线程都不能阻塞太旧,不然会影响其他连接的请求响应速度。"但是当并发量很大的时候,一个Reactor线程就会出现响应缓慢,连接超时等问题。"...可能是你在handler里面阻塞了太久。
通俗来讲,每个请求用一个线程来处理,一是可以保证字节序列传过来进行解码,分包,还有读取等的顺序性二是避免线程间资源竞争,线程切换的开销这就提高了系统性能
多线程处理io可能会导致信令乱序,造成业务失败。
同步问题并行只适用于上下文无关重复性高的操作否则各种锁性能反而下降
已有帐号?
无法登录?
社交帐号登录

我要回帖

更多关于 netty workergroup 的文章

 

随机推荐