• Pigeon源码跟踪之客户端获取服务


    在具体调用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);

      每个客户端都会缓存到一个服务端的连接,调用的时候根据负载均衡策略等选择一条连接进行通讯

  • 相关阅读:
    太原市圆通快递网点
    快递单号查询小工具
    C#快递单号查询源码
    爱快递快递接口使用说明
    如何把网站及数据库部署到Windows Azure
    从window.console&&console.log(123)浅谈JS的且运算逻辑(&&)
    C# Enum 简易权限设计 使用FlagsAttribute属性
    Lambda 表达式(C# 编程指南)
    C# list使用方法
    SharePoint Server 2013介绍v2
  • 原文地址:https://www.cnblogs.com/juniorMa/p/14506047.html
Copyright © 2020-2023  润新知