本章将描述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使用业务线程池今天处理具体的业务
|