• Dubbo基础(泛化、服务降级、主机绑定)


    Dubbo泛化

    我们每次去发布一个服务,必然会先定义一个接口,并且把这个接口放在一个api的jar包中,给到服务调用方来使用。本质上,对于开发者来说仍然是面向接口编程,而且对于使用者来说,可以不需要关心甚至不需要知道这个接口到底是怎么触发调用的。简而言之,泛化调用,最最直接的表现就是服务消费者不需要有任何接口的实现,就能完成服务的调用。

    代码实例:

    • provider

    在服务端定义了一个接口

    @DubboService(protocol = {"dubbo"})
    public class DemoService implements IDemoService{
    
        @Override
        public String getTxt() {
            return "Hello world!!!";
        }
    }
    

    注册到nacos的元数据

    side=provider
    
    methods=getTxt
    
    release=2.7.7
    
    deprecated=false
    
    dubbo=2.0.2
    
    pid=10884
    
    interface=com.springboot.dubbo.provider.services.IDemoService
    
    generic=false
    
    path=com.springboot.dubbo.provider.services.IDemoService
    
    protocol=dubbo
    
    application=spring-boot-dubbo-sample-provider
    
    dynamic=true
    
    category=providers
    
    anyhost=true
    
    timestamp=1608312655153
    
    • consumer
    @RestController
    public class DemoController {
        // 设置generic=true代表开启泛化功能
        @DubboReference(interfaceName = "com.springboot.dubbo.provider.services.IDemoService",generic = true,check = false)
        GenericService genericService;
    
        @GetMapping("/demo")
        public String demo(){
            //对象的传值
            Map<String,Object> user=new HashMap<>();
            user.put("",""); //key表达user对象中的属性,value表达属性的值
            return genericService.$invoke("getTxt",new String[0],null).toString();
        }
    }
    
    • 结果(调用http://localhost:port/demo)
    Hello world!!!
    

    服务降级

    @RestController
    public class SayController {
    
        @DubboReference(registry = {"shanghai","hunan"},
                protocol = "dubbo",
                loadbalance = "consistenthash",
                mock = "com.springboot.dubbo.consumer.SayHelloService",
                timeout = 500,
                cluster = "failfast",check = false,
                methods = {
                @Method(loadbalance = "",name ="sayHello" )
        },
                retries = 5)
        ISayHelloService sayHelloService;
    
        @GetMapping("/say")
        public String say(){
            return sayHelloService.sayHello("hello");
        }
    }
    

    主机绑定

    代码位置

    DubboBootstrap.start() -> exportServices() -> ServiceConfigBase.export() -> ServiceConfig.doExport() -> doExportUrls() -> doExportUrlsFor1Protocol()

    String host = findConfigedHosts(protocolConfig, registryURLs, map);
    Integer port = findConfigedPorts(protocolConfig, name, map);
    

    findConfigedHosts

     private String findConfigedHosts(ProtocolConfig protocolConfig,
                                     List<URL> registryURLs,
                                     Map<String, String> map) {
        boolean anyhost = false;
    
        String hostToBind = getValueFromConfig(protocolConfig, DUBBO_IP_TO_BIND);
        if (hostToBind != null && hostToBind.length() > 0 && isInvalidLocalHost(hostToBind)) {
            throw new IllegalArgumentException("Specified invalid bind ip from property:" + DUBBO_IP_TO_BIND + ", value:" + hostToBind);
        }
    
        // 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 (isInvalidLocalHost(hostToBind)) {
                anyhost = true;
                try {
                    logger.info("No valid ip found from environment, try to find valid host from DNS.");
                    hostToBind = InetAddress.getLocalHost().getHostAddress();
                } catch (UnknownHostException e) {
                    logger.warn(e.getMessage(), e);
                }
                if (isInvalidLocalHost(hostToBind)) {
                    if (CollectionUtils.isNotEmpty(registryURLs)) {
                        for (URL registryURL : registryURLs) {
                            if (MULTICAST.equalsIgnoreCase(registryURL.getParameter("registry"))) {
                                // skip multicast registry since we cannot connect to it via Socket
                                continue;
                            }
                            try (Socket socket = new Socket()) {
                                SocketAddress addr = new InetSocketAddress(registryURL.getHost(), registryURL.getPort());
                                socket.connect(addr, 1000);
                                hostToBind = socket.getLocalAddress().getHostAddress();
                                break;
                            } catch (Exception e) {
                                logger.warn(e.getMessage(), e);
                            }
                        }
                    }
                    if (isInvalidLocalHost(hostToBind)) {
                        hostToBind = getLocalHost();
                    }
                }
            }
        }
    
        map.put(BIND_IP_KEY, hostToBind);
    
        // registry ip is not used for bind ip by default
        String hostToRegistry = getValueFromConfig(protocolConfig, DUBBO_IP_TO_REGISTRY);
        if (hostToRegistry != null && hostToRegistry.length() > 0 && isInvalidLocalHost(hostToRegistry)) {
            throw new IllegalArgumentException("Specified invalid registry ip from property:" + DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry);
        } else if (StringUtils.isEmpty(hostToRegistry)) {
            // bind ip is used as registry ip by default
            hostToRegistry = hostToBind;
        }
    
        map.put(ANYHOST_KEY, String.valueOf(anyhost));
    
        return hostToRegistry;
    }
    
    • 查找环境变量中是否存在启动参数 [DUBBO_IP_TO_BIND] =服务注册的ip

    • 读取配置文件, dubbo.protocols.dubbo.host= 服务注册的ip

    • InetAddress.getLocalHost().getHostAddress() 获得本机ip地址

    • 通过Socket去连接注册中心,从而获取本机IP

    • 会轮询本机的网卡,直到找到合适的IP

    • 地址上面获取到的ip地址是bindip,如果需要作为服务注册中心的ip, DUBBO_IP_TO_REGISTRY -dDUBBO_IP_TO_REGISTRY=ip

    配置的优先级问题

    服务端配置的信息,都会装载到url上

    dubbo%3A%2F%2F169.254.99.173%3A20880%2Fcom.springboot.dubbo.ISayHelloService%3Fanyhost%3Dtrue%26application%3Dspring-boot-dubbo-sample-provider%26cluster%3Dfailover%26deprecated%3D
    false%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Dcom.springboot.dubbo.ISayHelloService%26methods%3DsayHello%26pid%3D10884%26release%3D2.7.7%26side%3Dprovider
    %26timestamp%3D1608312656576 
    

    非集群(cluster=failver)

    • 客户端没有配置

      • 以客户端优先
    • 客户端有配置

      • 方法层面的配置要优先于接口层面的配置, 接口层面的配置要优先于全局配置
      • 如果级别一样,以客户端的配置优先,服务端次之
  • 相关阅读:
    Micorosoft 2013年笔试题
    Dropbox推荐使用
    swift_枚举 | 可为空类型 | 枚举关联值 | 枚举递归 | 树的概念
    swift_简单值 | 元祖 | 流程控制 | 字符串 | 集合
    Swift函数的定义
    swift_Dictionary 字典
    Xcode创建Object-C程序
    Spring事务管理者与Spring事务注解--声明式事务
    JDK注解替代Hibernate的Entity映射
    关于JAVA EE项目在WEB-INF目录下的jsp页面如何访问WebRoot中的CSS和JS文件
  • 原文地址:https://www.cnblogs.com/snail-gao/p/14157876.html
Copyright © 2020-2023  润新知