本文將主要介紹Server端處理一次請求的流程,同時講解一個比較巧妙的設計——Filter。
根據前面的分析我們可以推斷出Server端處理網絡通信的組件爲NettyServer,對應處理具體事件的handler爲NettyHandler,它的構造函數需要一個ChannelHandler的參數,這裏傳遞的就是NettyServer實例的引用。這樣一來,handler對messageReceived()的事件處理,又傳遞給了NettyServer的receive()方法
| @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { NettyChannel channel = NettyChannel.getOrAddChannel(ctx.getChannel(), url, handler); try { handler.received(channel, e.getMessage()); } finally { NettyChannel.removeChannelIfDisconnected(ctx.getChannel()); } } |
NettyServer本身沒有實現receive方法,這個調用由基類AbstractPeer處理,而它也是再調用自己維護的ChannelHandler,也就是構造NettyServer時傳入的handler。這是一個ChannelHandlerDispatcher實例,它允許同時觸發一組普通的handler。實際構建時的handler爲new DecodeHandler(new HeaderExchangeHandler(handler)),HeaderExchangeHandler中有一部分處理的邏輯,同時還會調用外部傳遞handler。
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
30
31
32
33
34
35
36
37
38
39
40
41
|
publicvoidreceived(Channelchannel,Objectmessage)throwsRemotingException{
ExchangeChannelexchangeChannel=HeaderExchangeChannel.getOrAddChannel(channel);
try{
if(messageinstanceofRequest){
//
handle request.
Requestrequest=(Request)message;
if(request.isEvent()){
handlerEvent(channel,request);
}else{
if(request.isTwoWay()){
Responseresponse=handleRequest(exchangeChannel,request);
channel.send(response);
}else{
handler.received(exchangeChannel,request.getData());
}
}
}elseif(messageinstanceofResponse){
...
}else{
handler.received(exchangeChannel,message);
}
}finally{
HeaderExchangeChannel.removeChannelIfDisconnected(channel);
}
}
ResponsehandleRequest(ExchangeChannelchannel,Requestreq)throwsRemotingException{
Responseres=newResponse(req.getId(),req.getVersion());
//
find handler by message class.
Objectmsg=req.getData();
try{
//
handle data.
Objectresult=handler.reply(channel,msg);
res.setStatus(Response.OK);
res.setResult(result);
}catch(Throwablee){
res.setStatus(Response.SERVICE_ERROR);
res.setErrorMessage(StringUtils.toString(e));
}
returnres;
}
|
最後調用了handelr.reply()方法, 它的實現與具體的協議有關,比如默認配置下就是在DubboProtocol中構建的requestHandler,在createServer()方法中傳遞給Exchanger。
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 | private ExchangeServer createServer(URL url) { ... ExchangeServer server; try { server = Exchangers.bind(url, requestHandler); } catch (RemotingException e) { throw new RpcException("Fail to start server(url: " + url + ") " + e.getMessage(), e); } ... return server; } private ExchangeHandler requestHandler = new ExchangeHandlerAdapter() { public Object reply(ExchangeChannel channel, Object message) throws RemotingException { if (message instanceof Invocation) { Invocation inv = (Invocation) message; Invoker<?> invoker = getInvoker(channel, inv); RpcContext.getContext().setRemoteAddress(channel.getRemoteAddress()); return invoker.invoke(inv); } } }; Invoker<?> getInvoker(Channel channel, Invocation inv) throws RemotingException{ String serviceKey = serviceKey(port, path, inv.getAttachments().get(Constants.VERSION_KEY), inv.getAttachments().get(Constants.GROUP_KEY)); DubboExporter<?> exporter = (DubboExporter<?>) exporterMap.get(serviceKey); return exporter.getInvoker(); } |
看到了invoker.invoke(),也就是真正執行調用的地方。這個Invoker實例來自於根據serviceKey查找的Exporter,它是通過ExtensionLoader創建的,是一個ProtocolFilterWrapper實例。
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
|
public<T>Exporter<T>export(Invoker<T>invoker)throwsRpcException{
if(Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())){
returnprotocol.export(invoker);
}
returnprotocol.export(buildInvokerChain(invoker,Constants.SERVICE_FILTER_KEY,Constants.PROVIDER));
}
privatestatic<T>Invoker<T>buildInvokerChain(finalInvoker<T>invoker,Stringkey,Stringgroup){
Invoker<T>last=invoker;
List<Filter>filters=ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(),key,group);
if(filters.size()>0){
for(inti=filters.size()-1;i>=0;i--){
finalFilterfilter=filters.get(i);
finalInvoker<T>next=last;
last=newInvoker<T>(){
...
publicResultinvoke(Invocationinvocation)throwsRpcException{
returnfilter.invoke(next,invocation);
}
...
};
}
}
returnlast;
}
|
這裏會將原來的Invoker通過各種Filter包裝成一個InvokerChain,一次調用會依次經過這些FilterChain到達最終的Filter。在這些Filter中可以進行超時校驗、數據監控等工作,每個Filter相對獨立,使得代碼結構非常清晰,也便於爲新功能進行擴展。
這個鏈的結構是:除了初始傳入的Invoker外,對於每個Filter都新建一個Invoker,並返回最後一個創建的Invoker。當執行這些後來構建的Invoker.invoker()方法時,實際調用了filter.invoker(next, invocation),這樣會去執行filter中的邏輯,然後再由filter調用下一個Invoker的invoke方法。直至最後一個原始的Invoker,它的invoke方法不會調用filter,而是正常的invoke邏輯。
| invokerN.invoke()開始 -> filterN.invoke()開始 -> ... -> invoker1.invoke()開始 -> filter1.invoke()開始 -> invoker0.invoke()開始 -> invoker0.invoke()結束 -> filter1.invoke()結束 -> invoker1.invoke()結束 -> ... -> filterN.invoke()結束 -> invokerN.invoke()結束 |
以TimeoutFilter爲例具體來看一下
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@Activate(group=Constants.PROVIDER)
publicclassTimeoutFilterimplementsFilter{
publicResultinvoke(Invoker<?>invoker,Invocationinvocation)throwsRpcException{
longstart=System.currentTimeMillis();
Resultresult=invoker.invoke(invocation);
longelapsed=System.currentTimeMillis()-start;
if(invoker.getUrl()!=null
&&elapsed>invoker.getUrl().getMethodParameter(invocation.getMethodName(),"timeout",Integer.MAX_VALUE)){
//
log timeout info
}
returnresult;
}
}
|
在調用下一個Invoker的前後記錄時間,並將超時的信息打印出來。其中原始的Invoker來自JavassistProxyFactory創建的實例
|
public<T>Invoker<T>getInvoker(Tproxy,Class<T>type,URLurl){
finalWrapperwrapper=Wrapper.getWrapper(proxy.getClass().getName().indexOf('$')<0?proxy.getClass():type);
returnnewAbstractProxyInvoker<T>(proxy,type,url){
@Override
protectedObjectdoInvoke(Tproxy,StringmethodName,
Class<?>[]parameterTypes,
Object[]arguments)throwsThrowable{
returnwrapper.invokeMethod(proxy,methodName,parameterTypes,arguments);
}
};
}
|
基類的invoke方法調用子類的doInvoke,去執行真正的反射調用。Server端處理一次請求的流程就介紹到這裏。
文中提到的核心類包括
-
NettyServer
-
NettyHandler
-
HeaderExchangeHandler
-
DubboProtocol
-
ProtocolFilterWrapper
-
JavassistProxyFactory