dubbo处理调用请求涉及缓存问题
来源:互联网 发布:莫知我哀的莫的用法 编辑:程序博客网 时间:2024/05/29 11:07
一.场景
dubbo底层使用netty,一个boss线程,核心线程+1个worker。
读写io在worker线程去做。
每个worker会处理一部分socket读写。
高并发时,io线程不太会不足,原因是默认是核心线程+1。高并发时每个线程都会不断的在处理读写事件,cpu一直是处于忙的状态。这时增加io线程更多反而会因为cpu切换线程上下文而影响性能。
一般业务线程池不足可能性比较多,默认有200个线程。当然如果出现请求过多处理不过来,直接就抛错了,问题倒比较好查。
当然也可能会是网络出现瓶颈,内存及cpu出现瓶颈,需要用相应的工具命令查看。
之后会做实际测试。
而这里主要讲,worker线程在获取到socket读请求时,会从heap缓存中获取一个buffer。由于是堆缓存,不可避免一次内核到堆内存的拷贝。
二.原理
服务方处理消费方的调用流程如下:
1.一个读请求过来时,worker线程,首先从尝试从direct缓存区获取一个缓存,最多存储8块,是softReference类型的一个ByteBuf数组。
注:direct缓存默认在full gc时才会进行回收。如果没有full gc
用softReference不用担心由于缓存的原因。
注:这里如果没有则会创建一块direct缓存。
这里的direct缓存区是每个worker都有一个,所以不存在线程竞争问题。
2.将对应socket数据写入到这块direct缓存
3.创建一块heap内存,然后将direct缓存的数据写到这个堆内存
4.将之前创建的direct缓存放回到缓存池
5.将这个heap buffer交给后面的channelHandler处理。
后面会解码,channel handler处理也在io线程。
6.handler都处理完成后,会将这个解码后的消息交给另外一个线程池去做。这个线程池默认200个线程。
实际上还是发生了一次从direct缓存拷贝到堆内存。
源码:
private boolean read(SelectionKey k) { final SocketChannel ch = (SocketChannel) k.channel(); final NioSocketChannel channel = (NioSocketChannel) k.attachment(); final ReceiveBufferSizePredictor predictor = channel.getConfig().getReceiveBufferSizePredictor(); final int predictedRecvBufSize = predictor.nextReceiveBufferSize(); int ret = 0; int readBytes = 0; boolean failure = true; ByteBuffer bb = recvBufferPool.acquire(predictedRecvBufSize); try { while ((ret = ch.read(bb)) > 0) { readBytes += ret; if (!bb.hasRemaining()) { break; } } failure = false; } catch (ClosedChannelException e) { // Can happen, and does not need a user attention. } catch (Throwable t) { fireExceptionCaught(channel, t); } if (readBytes > 0) { bb.flip(); final ChannelBufferFactory bufferFactory = channel.getConfig().getBufferFactory(); final ChannelBuffer buffer = bufferFactory.getBuffer(readBytes); buffer.setBytes(0, bb); buffer.writerIndex(readBytes); recvBufferPool.release(bb); // Update the predictor. predictor.previousReceiveBufferSize(readBytes); // Fire the event. fireMessageReceived(channel, buffer); } else { recvBufferPool.release(bb); } if (ret < 0 || failure) { k.cancel(); // Some JDK implementations run into an infinite loop without this. close(channel, succeededFuture(channel)); return false; } return true; }
二.问题
1.最坏的情况下,这里direct缓存最大内存占用有多少?
底层用的是动态预计大小,
类:AdaptiveReceiveBufferSizePredictor
AdaptiveReceiveBufferSizePredictor最大限制是:6k。
也就是说direct dubbo用到最多6k*当前worker个数。
2.如果优化怎么优化?
在处理读请求时,最终还是会有一次direct缓存到heap堆的拷贝。
优化的话,这里要换成netty4,使用direct缓存池。
阅读全文
0 0
- dubbo处理调用请求涉及缓存问题
- dubbo 请求调用过程分析
- dubbo请求调用过程分析
- dubbo 请求调用过程分析
- Dubbo服务调用问题
- XMLHttpRequest请求的缓存问题的处理方案
- 通过dubbo暴露接口调用方法,及基于zookeeper的dubbo涉及配置文件
- 通过dubbo暴露接口调用方法,及基于zookeeper的dubbo涉及配置文件
- 通过dubbo暴露接口调用方法,及基于zookeeper的dubbo涉及配置文件
- ajax请求缓存问题
- ajax请求缓存问题
- get请求缓存问题
- Dubbo处理TCP拆包粘包问题
- dubbo处理自定义异常问题
- Android开发全程记录(十六)——android调用接口发送http请求缓存处理
- 系统解耦问题-不同系统间dubbo调用的异常处理-ExceptionFilter
- dubbo本地缓存提供者信息配置问题
- Windows 下用 Tomcat 启动网络服务涉及的缓存问题
- Java super关键字
- set 中对象元素插入与查找
- 用单片机定时器操作流水灯
- JavaScript 高级程序设计
- MOOC清华《程序设计基础》第9章:自动售卖程序 v 1.0
- dubbo处理调用请求涉及缓存问题
- seafile从sqlite迁移到mysql
- String
- Spring基础
- 拓扑范例
- 多线程下双重检查锁的问题及解决方法
- jquery源码学习
- eclipse使用技巧
- LeetCode 70 Climbing Stairs(Python详解及实现)