motan源码分析十一:部分特性
本章将描述motan部分的特性并对源码进行分析。
1.requestid的维护,使用了当前时间左移20位,再和一个自增变量组合
public class RequestIdGenerator { protected static final AtomicLong offset = new AtomicLong(0); protected static final int BITS = 20; protected static final long MAX_COUNT_PER_MILLIS = 1 << BITS; /** * 获取 requestId * * @return */ public static long getRequestId() { long currentTime = System.currentTimeMillis(); long count = offset.incrementAndGet(); while(count >= MAX_COUNT_PER_MILLIS){ synchronized (RequestIdGenerator.class){ if(offset.get() >= MAX_COUNT_PER_MILLIS){ offset.set(0); } } count = offset.incrementAndGet(); } return (currentTime << BITS) + count; } public static long getRequestIdFromClient() { // TODO 上下文 requestid return 0; } }
2.限流,motan支持简单的限流,是利用filter来实现的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | @SpiMeta (name = "active" ) @Activation (sequence = 1 ) public class ActiveLimitFilter implements Filter { @Override public Response filter(Caller<?> caller, Request request) { int maxAcvitivyCount = caller.getUrl().getIntParameter(URLParamType.actives.getName(), URLParamType.actives.getIntValue()); if (maxAcvitivyCount > 0 ) { int activeCount = RpcStats.getServiceStat(caller.getUrl()).getActiveCount(); if (activeCount >= maxAcvitivyCount) { throw new MotanServiceException(String.format( "Request(%s) active count exceed the limit (%s), referer:%s" , request, maxAcvitivyCount, caller.getUrl()), MotanErrorMsgConstant.SERVICE_REJECT); } } long startTime = System.currentTimeMillis(); RpcStats.beforeCall(caller.getUrl(), request); try { Response rs = caller.call(request); RpcStats.afterCall(caller.getUrl(), request, true , System.currentTimeMillis() - startTime); return rs; } catch (RuntimeException re) { RpcStats.afterCall(caller.getUrl(), request, false , System.currentTimeMillis() - startTime); throw re; } } } |
3.对于连续失败的client进行不可用操作
void incrErrorCount() { long count = errorCount.incrementAndGet(); // 如果节点是可用状态,同时当前连续失败的次数超过限制maxClientConnection次,那么把该节点标示为不可用 if (count >= maxClientConnection && state.isAliveState()) { synchronized (this) { count = errorCount.longValue(); if (count >= maxClientConnection && state.isAliveState()) { LoggerUtil.error("NettyClient unavailable Error: url=" + url.getIdentity() + " " + url.getServerPortStr()); state = ChannelState.UNALIVE; } } } } void resetErrorCount() { errorCount.set(0); if (state.isAliveState()) { return; } synchronized (this) { if (state.isAliveState()) { return; } // 如果节点是unalive才进行设置,而如果是 close 或者 uninit,那么直接忽略 if (state.isUnAliveState()) { long count = errorCount.longValue(); // 过程中有其他并发更新errorCount的,因此这里需要进行一次判断 if (count < maxClientConnection) { state = ChannelState.ALIVE; LoggerUtil.info("NettyClient recover available: url=" + url.getIdentity() + " " + url.getServerPortStr()); } } } }
4.支持多注册中心,因此cluster的refer集合是所有注册中心包含服务器的集合,如果同一个服务器在不同的注册中心注册,则cluster中当作两个服务器
5.服务端的采用boss线程池+工作线程池+业务线程池的处理方式
1 2 3 4 5 6 7 8 9 10 11 12 13 | private final static ChannelFactory channelFactory = new NioServerSocketChannelFactory( //boss线程池和工作线程池,主要负责接收消息 Executors.newCachedThreadPool( new DefaultThreadFactory( "nettyServerBoss" , true )), Executors.newCachedThreadPool( new DefaultThreadFactory( "nettyServerWorker" , true ))); private StandardThreadExecutor standardThreadExecutor = null ; //业务线程池,负责具体的业务处理 standardThreadExecutor = (standardThreadExecutor != null && !standardThreadExecutor.isShutdown()) ? standardThreadExecutor : new StandardThreadExecutor(minWorkerThread, maxWorkerThread, workerQueueSize, new DefaultThreadFactory( "NettyServer-" + url.getServerPortStr(), true )); standardThreadExecutor.prestartAllCoreThreads(); final NettyChannelHandler handler = new NettyChannelHandler(NettyServer. this , messageHandler, standardThreadExecutor); //handler使用业务线程池今天处理具体的业务 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?