zoukankan      html  css  js  c++  java
  • dubbo备忘录

    1.负载均衡策略

    Random LoadBalance :随机,按权重设置随机概率。 在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
    RoundRobin LoadBalance :轮询,按公约后的权重设置轮询比率。 存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
    LeastActive LoadBalance :最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
    ConsistentHash LoadBalance :一致性 Hash,相同参数的请求总是发到同一提供者。当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
        算法参见:http://en.wikipedia.org/wiki/Consistent_hashing
        缺省只对第一个参数 Hash,如果要修改,请配置 <dubbo:parameter key="hash.arguments" value="0,1" />
        缺省用 160 份虚拟节点,如果要修改,请配置 <dubbo:parameter key="hash.nodes" value="320" />

    2.集群容错策略

    Failover Cluster:失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries="2" 来设置重试次数(不含第一次)。
    Failfast Cluster:快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
    Failsafe Cluster:失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
    Failback Cluster:失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
    Forking Cluster:并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks="2" 来设置最大并行数。
    Broadcast Cluster:广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。

    3.dubbo停机

    1.服务提供方
    停止时,先标记为不接收新请求,新请求过来时直接报错,让客户端重试其它机器。
    然后,检测线程池中的线程是否正在运行,如果有,等待所有线程执行完成,除非超时,则强制关闭。
    2.服务消费方
    停止时,不再发起新的调用请求,所有新的调用在客户端即报错。
    然后,检测有没有请求的响应还没有返回,等待响应返回,除非超时,则强制关闭。
    这里还有两件事,取消注册,以及取消订阅

    4.dubbo启动

    5.dubbo注册ip

    DUBBO启动时通过ServiceConfig 的 findConfigedHosts寻找本机地址
    首先是判断是否有配置host ip,通过环境变量DUBBO_IP_TO_REGISTRY查找,第二优先级是通过配置中的dubbo.protocol.host来获取本机ip,并注册
    如果没有配置,那么通过本机的hostname来查找本机的ip;

    /**
         * Register & bind IP address for service provider, can be configured separately.
         * Configuration priority: environment variables -> java system properties -> host property in config file ->
         * /etc/hosts -> default network address -> first available network address
         *
         * @param protocolConfig
         * @param registryURLs
         * @param map
         * @return
         */
        private String findConfigedHosts(ProtocolConfig protocolConfig, List<URL> registryURLs, Map<String, String> map) {
            boolean anyhost = false;
    
            String hostToBind = getValueFromConfig(protocolConfig, Constants.DUBBO_IP_TO_BIND);
    
            // if bind ip is not found in environment, keep looking up
            if (StringUtils.isEmpty(hostToBind)) {
                hostToBind = protocolConfig.getHost();
                if (provider != null && StringUtils.isEmpty(hostToBind)) {
                    hostToBind = provider.getHost();
                }
    
                if (StringUtils.isEmpty(hostToBind)) {
                    anyhost = true;
                    hostToBind = getLocalHost();
    
                    if (StringUtils.isEmpty(hostToBind)) {
                        hostToBind = findHostToBindByConnectRegistries(registryURLs);
                    }
                }
            }
    
            map.put(Constants.BIND_IP_KEY, hostToBind);
    
            // registry ip is not used for bind ip by default
            String hostToRegistry = getValueFromConfig(protocolConfig, Constants.DUBBO_IP_TO_REGISTRY);
            if (StringUtils.isEmpty(hostToRegistry)) {
                // bind ip is used as registry ip by default
                hostToRegistry = hostToBind;
            }
    
            map.put(Constants.ANYHOST_KEY, String.valueOf(anyhost));
    
            return hostToRegistry;
        }
    

    6.服务端连接池

    系统默认使用FixedThreadPoll,连接池大小默认200,队列大小默认为0;

    7.消费端Reference初始化

    消费端会通过@Reference来注入provider引用,对应的就是dubbo的ReferenceBean,实现了spring的FactoryBean(FactoryBean 通常是用来创建比较复杂的bean);
    参考dubbo官方文档









    8.dubbo调用链

    
    //消费端发送请求
    InvokerInvocationHandler.invoke 
        MockClusterInvoker.invoke
            AbstractInvoker.invoke
                DubboInvoker.doInvoke(final Invocation invocation)
                    ReferenceCountExchangeClient.request(Object request, int timeout)
                        HeaderExchangeClient.request(Object request, int timeout)
                            HeaderExchangeChannel.request(Object request, int timeout)
                                AbstractPeer.send(Object message)
                                    NettyChannel.send(Object message, boolean sent)
                                        AbstractChannel.writeAndFlush(Object msg)
    
    
    
    //服务端接收请求
    netty
        AllChannelHandler.received(Channel channel, Object message)
    asyn-----------------------------------------------------
    
    ChannelEventRunnable.run()
        DecodeHandler.received(Channel channel, Object message)
            HeaderExchangeHandler.received(Channel channel, Object message)
    			DubboProtocol.reply(ExchangeChannel channel, Object message)
    				CallbackRegistrationInvoker.invoke(Invocation invocation)
    					ProtocolFilterWrapper$1.invoke(next, invocation)
    					.
    					.
    					.
    					AbstractProxyInvoker.invoke(Invocation invocation)
    			HeaderExchangeChannel.send(response)
    			
    			
    //消费端接受响应
    netty
        AllChannelHandler.received(Channel channel, Object message)
    asyn-----------------------------------------------------
    
    ChannelEventRunnable.run()
        DecodeHandler.received(Channel channel, Object message)
            HeaderExchangeHandler.received(Channel channel, Object message)
    		    HeaderExchangeHandler.handleResponse(channel, (Response) message)
    			    DefaultFuture.received(channel, response) 获取到response对应的DefaultFuture,并将response写入DefaultFuture,将DefaultFuture置为completed
    



    9.处理请求(处理响应)的线程池创建链路

    //DubboProtocol.java
    @Override
        public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
            URL url = invoker.getUrl();
    
            // export service
    
            //export an stub service for dispatching event
    
            //创建ExchangeServer
            openServer(url);
            optimizeSerialization(url);
    
            return exporter;
        }
    
    private void openServer(URL url) {
        // find server.
        String key = url.getAddress();
        //client can export a service which's only for server to invoke
        boolean isServer = url.getParameter(IS_SERVER_KEY, true);
        if (isServer) {
            ExchangeServer server = serverMap.get(key);
            if (server == null) {
                synchronized (this) {
                    server = serverMap.get(key);
                    //如果第一次,那么需要创建ExchangeServer
                    if (server == null) {
                        serverMap.put(key, createServer(url));
                    }
                }
            } else {
                // server supports reset, use together with override
                server.reset(url);
            }
        }
    }
    
    
    //WrappedChannelHandler.java
    public WrappedChannelHandler(ChannelHandler handler, URL url) {
        this.handler = handler;
        this.url = url;
        //在这里根据url上的配置,去创建指定thread数量,指定队列数量的线程池
        executor = (ExecutorService) ExtensionLoader.getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url);
    
        String componentKey = Constants.EXECUTOR_SERVICE_COMPONENT_KEY;
        if (CONSUMER_SIDE.equalsIgnoreCase(url.getParameter(SIDE_KEY))) {
            componentKey = CONSUMER_SIDE;
        }
        DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();
        dataStore.put(componentKey, Integer.toString(url.getPort()), executor);
    }
    
    
  • 相关阅读:
    cocos creator 场景如何透明,多个canvas层级显示
    c/c++导出lua绑定
    c++自动导出lua绑定
    获取Sprite上某一个点的透明度
    cocos2d-x lua中实现异步加载纹理
    keystore找回密码
    xcode 制作静态库文件(.a)
    Ajax学习笔记之一----------第一个Ajax Demo[转载]
    lua调用java java调用lua[转载]
    WPF中模板选择和DataContext的一些使用
  • 原文地址:https://www.cnblogs.com/IC1101/p/11387164.html
Copyright © 2011-2022 走看看