zuul 2.1.2 比zuul 1性能提高了4倍。
在 ZuulServerChannelInitializer 中初始化:
IdleStateHandler
CloseOnIdleStateHandler
... passport
PassportStateServerHandler
... tcp
SourceAddressChannelHandler
ServerChannelMetrics
PerEventLoopMetricsChannelHandler.Connections
ElbProxyProtocolChannelHandler(如果构造函数入参为false不执行此handler)
MaxInboundConnectionsHandler(属于throttle,如果构造函数入参为0,不执行此handler)
... http1
HttpServerCodec属于codec, netty自带
Http1ConnectionCloseHandler (ChannelDuplexHandler)
Http1ConnectionExpiryHandler (outbound)
... http
PassportStateHttpServerHandler
HttpRequestReadTimeoutHandler(如果设置了httpRequestReadTimeout不为-1)
HttpServerLifecycleChannelHandler
HttpBodySizeRecordingChannelHandler
HttpMetricsChannelHandler
PerEventLoopMetricsChannelHandler.HttpRequests
AccessLogChannelHandler
ServerStatusHeaderHandler
StripUntrustedProxyHeadersHandler
... zuul handlers
有个rateLimitingChannelHandlerProvider的properties配置,不知道是哪个ChannelHandler?
LoggingHandler
ClientRequestReceiver
PassportLoggingHandler
ZuulFilterChainHandler 初始化一个Endpoint(endpoint指的是后面的服务),EndpointFilter初始化clientManager,是netty到后端服务的netty连接。
ClientResponseWriter
每个Endpoint是一个Filter。
ProxyEndpoint 每个请求对应一个实例,但是重传请求是相同的实例,因为有成员变量的状态需要变更,比如重传次数等。
客户端的管理在BasicNettyOrigin类中,它的构造函数初始化DefaultClientChannelManager,DefaultClientChannelManager构造函数初始化ConnectionPoolConfigImpl,它包含了Bootstrap的option的值,DefaultClientChannelManager还初始化ConcurrentHashMap
对象,它的值PerServerConnectionPool含有到该Server的所有连接。此外DefaultClientChannelManager还有各种计数器和计时器。
BasicNettyOrigin 构造函数调用DefaultClientChannelManager的init方法,初始化netty的DefaultOriginChannelInitializer类。
handler:
PassportStateOriginHandler(duplex)
SslHandler (如果要ssl的话)
HttpClientCodec (duplex)
PassportStateHttpClientHandler (duplex)
LoggingHandler (duplex, netty)
HttpMetricsChannelHandler (inbound)
HttpClientLifecycleChannelHandler (duplex)
ConnectionPoolHandler (duplex)
ZuulEndPointRunner(BaseZuulFilterRunner)执行filter方法:
final HttpResponseMessage zuulResp = filter(endpoint, zuulReq);
syncFilter.apply(inMesg); // syncFilter即ProxyEndpoint
ProxyEndpoint执行proxyRequestToOrigin方法
private void proxyRequestToOrigin() {
Promise promise = null;
try {
attemptNum += 1;
requestStat = createRequestStat();
origin.preRequestChecks(zuulRequest);
concurrentReqCount++;
promise = origin.connectToOrigin(zuulRequest, channelCtx.channel().eventLoop(), attemptNum, passport, chosenServer);
logOriginServerIpAddr();
currentRequestAttempt = origin.newRequestAttempt(chosenServer.get(), context, attemptNum);
requestAttempts.add(currentRequestAttempt);
passport.add(PassportState.ORIGIN_CONN_ACQUIRE_START);
if (promise.isDone()) {
operationComplete(promise);
} else {
promise.addListener(this);
}
}
catch (Exception ex) {
LOG.error("Error while connecting to origin, UUID {} " + context.getUUID(), ex);
logOriginServerIpAddr();
if (promise != null && ! promise.isDone()) {
promise.setFailure(ex);
} else {
errorFromOrigin(ex);
}
}
}
上面的代码可总结成三步:
1)BasicNettyOrigin 的connectToOrigin方法获取连接
2)ProxyEndpoint的operationComplete方法,调用自身的onOriginConnectSucceeded方法
3)onOriginConnectSucceeded调用自身的writeClientRequestToOrigin方法发送数据:
private void writeClientRequestToOrigin(final PooledConnection conn) {
final Channel ch = conn.getChannel(); // ch 客户端channel
passport.setOnChannel(ch);
context.set("_origin_channel", ch);
context.set(POOLED_ORIGIN_CONNECTION_KEY, conn);
// empty body
preWriteToOrigin(chosenServer.get(), context); // 空的
final ChannelPipeline pipeline = ch.pipeline();
originResponseReceiver = getOriginResponseReceiver(); // 获取client inbound handler,用new 的方式,并且OriginResponseReceiver构造函数传入ProxyEndpoint,即netty server的ctx。用这个ctx将后端服务发来的报发送到server。
pipeline.addBefore("connectionPoolHandler", OriginResponseReceiver.CHANNEL_HANDLER_NAME, originResponseReceiver);
// check if body needs to be repopulated for retry
repopulateRetryBody();
ch.write(zuulRequest);
writeBufferedBodyContent(zuulRequest, ch);
ch.flush();
//Get ready to read origin's response
ch.read();
originConn = conn;
channelCtx.read(); // 从服务器的channel读取当前请求余下的数据
}
至此完成将zuul的netty server的数据发送到netty client。
上面的函数中:
originResponseReceiver = getOriginResponseReceiver();
pipeline.addBefore("connectionPoolHandler", OriginResponseReceiver.CHANNEL_HANDLER_NAME, originResponseReceiver);
将OriginResponseReceiver,一个DuplexHandler动态加载到client的pipeline中。它的构造函数需要ProxyEndpoint,用来写入到server。
TO BO CONTINUE