zoukankan      html  css  js  c++  java
  • 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);

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

  • 相关阅读:
    OpenVAS安装过程
    网络攻防环境搭建
    kali linux 安装过程
    20159217《网络攻防实践》第三周学习总结
    网络攻防实践第二周学习总结
    移动平台课程总结
    Android实践项目汇报
    性能测试四十六:Linux 从网卡模拟延时和丢包的实现
    性能测试四十五:性能测试策略
    性能测试四十四:性能优化思路
  • 原文地址:https://www.cnblogs.com/juniorMa/p/14506047.html
Copyright © 2011-2022 走看看