在具体调用ServiceFactory.getService时,实际会调用serviceProxy.getProxy(invokerConfig),进一步调用AbstractServiceProxy#getProxy方法,这个方法的实现逻辑大致如下:
1 检查interface,url,protocol等参数合法性,如果url没有设置,默认使用接口全限定名,如果protocol不为空,且等于default,则修改成@DEFAULT@,同时更新url加上这个协议前缀
2 双重加锁检查invokeConfig对应的服务是否以存在,不存在先尝试启动调用方启动类InvokerBootStrap
3 先根据配置的序列方式获取相应的序列化类,再根据invokerConfig创建动态代理:ServiceInvocationProxy
4 如果配置中的负载均衡配置存在,注册服务到负载均衡管理器中
5 注册区域策略服务
6 ClientManager.getInstance().registerClients(invokerConfig)注册客户端到注册中心(默认为zk)
7 缓存服务
本文分析下第6条
public static void init() { registerBizProcessFilter(new GenericImplFilter()); if (!isInitialized) { registerBizProcessFilter(new InvokerDataFilter()); if (Constants.MONITOR_ENABLE) { registerBizProcessFilter(new RemoteCallMonitorInvokeFilter()); } registerBizProcessFilter(new DegradationFilter()); registerBizProcessFilter(new FlowControlPigeonClientFilter()); registerBizProcessFilter(new ClusterInvokeFilter()); registerBizProcessFilter(new GatewayInvokeFilter()); registerBizProcessFilter(new ContextPrepareInvokeFilter()); registerBizProcessFilter(new RemoteCallInvokeFilter()); bizInvocationHandler = createInvocationHandler(bizProcessFilters); isInitialized = true; } }
先看客户端的动态代理过程
com.dianping.pigeon.remoting.invoker.proxy.AbstractServiceProxy
public <T> T getProxy(InvokerConfig<T> invokerConfig) { if (invokerConfig.getServiceInterface() == null) { throw new IllegalArgumentException("service interface is required"); } else { if (StringUtils.isBlank(invokerConfig.getUrl())) { invokerConfig.setUrl(ServiceFactory.getServiceUrl(invokerConfig)); } String protocolPrefix; if (!StringUtils.isBlank(invokerConfig.getProtocol()) && !invokerConfig.getProtocol().equalsIgnoreCase("default")) { protocolPrefix = "@" + invokerConfig.getProtocol().toUpperCase() + "@"; if (!invokerConfig.getUrl().startsWith(protocolPrefix)) { invokerConfig.setUrl(protocolPrefix + invokerConfig.getUrl()); } } protocolPrefix = null; Object service = services.get(invokerConfig); if (service == null) { try { InvokerBootStrap.startup(); service = SerializerFactory.getSerializer(invokerConfig.getSerialize()).proxyRequest(invokerConfig); if (StringUtils.isNotBlank(invokerConfig.getLoadbalance())) { LoadBalanceManager.register(invokerConfig.getUrl(), invokerConfig.getGroup(), invokerConfig.getLoadbalance()); }
public abstract class DefaultAbstractSerializer implements Serializer { public DefaultAbstractSerializer() { } public Object proxyRequest(InvokerConfig<?> invokerConfig) throws SerializationException { return Proxy.newProxyInstance(ClassUtils.getCurrentClassLoader(invokerConfig.getClassLoader()), new Class[]{invokerConfig.getServiceInterface()}, new ServiceInvocationProxy(invokerConfig, InvokerProcessHandlerFactory.selectInvocationHandler(invokerConfig))); }
public class ServiceInvocationProxy implements InvocationHandler
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); Class<?>[] parameterTypes = method.getParameterTypes(); if (method.getDeclaringClass() == Object.class) { return method.invoke(this.handler, args); } else if ("toString".equals(methodName) && parameterTypes.length == 0) { return this.handler.toString(); } else if ("hashCode".equals(methodName) && parameterTypes.length == 0) { return this.handler.hashCode(); } else { return "equals".equals(methodName) && parameterTypes.length == 1 ? this.handler.equals(args[0]) : this.extractResult(this.handler.handle(new DefaultInvokerContext(this.invokerConfig, methodName, parameterTypes, args)), method.getReturnType()); } }
DefaultInvokerContext 这个就好玩了
public class DefaultInvokerContext extends AbstractInvocationContext implements InvokerContext { private InvokerConfig<?> invokerConfig; private String methodName; private Class<?>[] parameterTypes; private Object[] arguments; private Client client;//tcp客户端 private boolean isDegraded = false;
注意这里的client可是null的,那么什么时候变成的具体值呢?
ClusterInvokeFilter()
public class ClusterInvokeFilter extends InvocationInvokeFilter { private static final Logger logger = LoggerLoader.getLogger(ClusterInvokeFilter.class); private Monitor monitor = MonitorLoader.getMonitor(); public ClusterInvokeFilter() { } public InvocationResponse invoke(ServiceInvocationHandler handler, InvokerContext invocationContext) throws Throwable { invocationContext.getTimeline().add(new TimePoint(TimePhase.CL)); InvokerConfig<?> invokerConfig = invocationContext.getInvokerConfig(); Cluster cluster = ClusterFactory.selectCluster(invokerConfig.getCluster()); if (cluster == null) { throw new IllegalArgumentException("Unsupported cluster type:" + cluster); } else { try { return cluster.invoke(handler, invocationContext);
FailfastCluster
public InvocationResponse invoke(ServiceInvocationHandler handler, InvokerContext invocationContext) throws Throwable { InvokerConfig<?> invokerConfig = invocationContext.getInvokerConfig(); InvocationRequest request = InvokerUtils.createRemoteCallRequest(invocationContext, invokerConfig); boolean timeoutRetry = invokerConfig.isTimeoutRetry(); if (!timeoutRetry) { Client remoteClient = this.clientManager.getClient(invokerConfig, request, (List)null); invocationContext.setClient(remoteClient); try { return handler.handle(invocationContext);
每个客户端都会缓存到一个服务端的连接,调用的时候根据负载均衡策略等选择一条连接进行通讯