【Dubbo3高级特性】「实战开发」自定义扩展实现Dubbo服务对外暴露的主机地址实战开发指南

news2024/9/21 20:32:02

内容主旨

本篇文章主要介绍了如何进行自定义Dubbo服务对外暴露的主机地址的实战技术方案,其中我们需要针对于服务提供者侧的host主机暴漏的目的以及如何进行定制化处理

特性说明

在Dubbo中,Provider启动时主要做两个事情

  1. 启动服务提供者的server端实例。
  2. 服务自身向注册中心注册服务基本信息(服务IP地址、端口以及相关的一些服务实例级别的信息)。

启动server时需要绑定socket套接字以及监听对应的port端口,向注册中心注册自身服务时也是需要发送socket唯一标识服务地址

开发Dubbo的阔扩展暴漏主机地址前需要的问题

  1. Dubbo中不设置host时默认host是什么?

  2. Dubbo中如何指定服务的host,我们是否可以用hostname或domain代替IP地址作为host?

  3. 使用docker时,有时需要设置端口映射,此时,启动server时绑定的socket和向注册中心注册的 socket 使用不同的端口号,此时又该如何设置?

使用场景

不设置host时,使用默认host,一般的dubbo协议配置如下:

xml配置方式

    <dubbo:protocol name="dubbo" port="20890" />

yaml配置方式

dubbo:
  protocol:
	name: dubbo
	port: 20890  	

可以看到,按照上面的配置方式,我们只配置了端口号,没有配置host,此时设置的host是什么呢?
查看源码得知,在 org.apache.dubbo.config.ServiceConfig#findConfigedHosts() 方法获取host值。

    /**
     * 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, 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 {
                    if (logger.isDebugEnabled()) {
                        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;
    }

可以从源码看出来像关于读取host值的优先级,通过注释可以得知它的加载顺序如下。

Configuration priority: environment variables -> java system properties -> host property in config file ->
     * /etc/hosts -> default network address -> first available network address

其中最主要还是依赖通过hostToBind = InetAddress.getLocalHost().getHostAddress();获取默认host。

查找host的顺序

缺省主机IP查找顺序:
  1. 通过 ​LocalHost.getLocalHost() ​获取本机地址。
  2. 如果是 ​127.* ​等 loopback 地址,则扫描各网卡,获取网卡 IP。
主机配置

注册的地址如果获取不正确,比如需要注册公网地址,可以在​ /etc/hosts​ 中加入:机器名 公网IP,比如:

www.xxx.com  205.182.23.114

在 ​dubbo.xml ​中加入主机地址的配置:

<dubbo:protocol host="205.182.23.114">

或在 ​dubbo.properties​ 中加入主机地址的配置:端口配置

dubbo.protocol.host=205.182.23.201

application.yml文件对应的配置信息

dubbo:
  protocol:
	host: 205.182.23.201
其返回值如下:
  1. 未联网时,返回 127.0.0.1
  2. 在阿里云服务器中,返回私有地址,如: 172.18.46.234
  3. 在本机测试时,返回公有地址,如: 30.5.10.11

那在dubbo中如何指定服务的socket?

除此之外,可以通过dubbo.protocol或dubbo.provider的host属性对host进行配置,支持IP地址和域名,如下:

xml配置方式

<dubbo:protocol name="dubbo" port="20890" host="www.xxx.com"/>

yaml配置方式

dubbo:
  protocol:
	name: dubbo
	port: 20890  	
	host: www.xxx.com

开发Dubbo的阔扩展暴漏主机地址前需要的问题

在使用docker时,有时需要设置端口映射,此时,启动 server 时绑定的 socket 和向注册中心注册的 socket 使用不同的端口号,此时又该如何设置?

dubbo通过环境变量设置host

有些部署场景需要动态指定服务注册的地址,如docker bridge网络模式下要指定注册宿主机 ip 以实现外网通信。dubbo提供了两对启动阶段的系统属性,用于设置对外通信的ip、port地址。

  • DUBBO_IP_TO_REGISTRY — 注册到注册中心的ip地址
  • DUBBO_PORT_TO_REGISTRY — 注册到注册中心的port端口
  • DUBBO_IP_TO_BIND — 监听ip地址
  • DUBBO_PORT_TO_BIND — 监听port端口

以上四个配置项均为可选项,如不配置 dubbo会自动获取ip与端口,请根据具体的部署场景灵活选择配置。 dubbo支持多协议,如果一个应用同时暴露多个不同协议服务,且需要为每个服务单独指定ip或port,请分别在以上属性前加协议前缀。 如:

HESSIAN协议的定制化绑定

  • HESSIAN_DUBBO_IP_TO_REGISTRY hessian协议注册的ip
  • HESSIAN_DUBBO_PORT_TO_BIND hessian协议绑定的port

Dubbo协议的定制化绑定

  • DUBBO_DUBBO_PORT_TO_BIND dubbo协议注册的ip
  • DUBBO_DUBBO_PORT_TO_BIND dubbo协议绑定的port

PORT_TO_REGISTRY及IP_TO_REGISTRY与PORT_TO_BIND及IP_TO_BIND的关系

  • PORT_TO_REGISTRY或IP_TO_REGISTRY不会用作默认 PORT_TO_BIND 或 IP_TO_BIND,但是反过来是成立的
    如设置 PORT_TO_REGISTRY=20881 IP_TO_REGISTRY=30.5.97.6,则 PORT_TO_BIND IP_TO_BIND 不受影响。

  • 如果设置 PORT_TO_BIND=20881 IP_TO_BIND=30.5.97.6,则默认 PORT_TO_REGISTRY=20881 IP_TO_REGISTRY=30.5.97.6。

此外对应的缺省主机端口与协议相关:
在这里插入图片描述

总结

可以通过dubbo.protocol或dubbo.provider的host属性对host进行配置,支持IP地址和域名。但此时注册到注册中心的IP地址和监听IP地址是同一个值。

为了解决在虚拟环境或局域网内consumer无法与provider通信的问题,可以通过环境变量分别设置注册到注册中心的IP地址和监听IP地址,其优先级高于dubbo.protocol或dubbo.provider的host配置

Docker的实战案例分析

Dockerfile文件

FROM openjdk:8-jdk-alpine
ADD target/dubbo-app.jar app.jar
ENV JAVA_OPTS=""
ENTRYPOINT exec java $JAVA_OPTS -jar /app.jar
docker build --no-cache -t app. 

Create and run containers from mirroring

启动Zookeeper注册中心服务

docker run --name zkserver --restart always -d zookeeper:3.4.9

采用Docker的方式加入DUBBO_IP_TO_REGISTRY以及DUBBO_PORT_TO_REGISTRY的环境变量

docker run -e DUBBO_IP_TO_REGISTRY=30.5.97.6 -e DUBBO_PORT_TO_REGISTRY=20881 -p 30.5.97.6:20881:20880 --link zkserver:zkserver -it --rm dubbo-app

通过环境变量DUBBO_IP_TO_REGISTRY=30.5.97.6 和 DUBBO_PORT_TO_REGISTRY=20881设置提供程序以注册注册中心的IP地址和端口通过-p 30.5.97.6:20881:20880实现端口映射,其中20880是DUBBO自动选择的侦听端口。

没有监控IP配置,因此它将侦听0.0.0.0(所有IP)。启动后,提供程序的注册地址为30.5.97.6:20881,容器的侦听地址为:0.0.0.0:20880。

配置对应对比图(修改之前)

在这里插入图片描述
我们修改了对应的参数
在这里插入图片描述

配置对应对比图(修改之后)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/79681.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于C++实现(控制台+界面)通讯录管理系统【100010012】

个人通讯录管理系统 问题描述&#xff1a; 主要内容&#xff1a; 个人通讯录是记录了同学&#xff08;包含一起上学的学校名称&#xff09;、同事&#xff08;包含共事的单位名称&#xff09;、朋友&#xff08;包含认识的地点&#xff09;、亲戚&#xff08;包含称呼&#…

Python小炼(2):文件操作

"一封信&#xff0c;写下太多如果" 如果有一定语言基础的&#xff0c;一定对文件操作十分得"熟悉"!当然&#xff0c;这种熟悉是 引起人恼怒的 也不为过。 python 也有自己的文件操作&#xff0c;那它跟C\C又有何不同呢&#xff1f; 一、文件的基本操作 (…

中国宗教活动场所数据库(数据+python代码)

通常研究&#xff0c;宗教活动场所与公司避税行为&#xff0c;社会整体信任水平以及民营企业创始资金来源等元素相关联。例如&#xff0c;企业注册地的宗教传统负向影响公司避税&#xff0c;企业注册地的宗教传统通过提高管理者的道德意识和强化管理者的风险规避倾向两条机制抑…

Swagger总结

目录 简介&#xff1a; openAPI Springfox&#xff1a; 简介 Springfox的使用 SwaggerUI的使用 Swagger配置 设置扫描的包 设置范围 Swagger常用注解&#xff1a; 控制类、方法生成接口信息 ApiParam ApiModel ApiModelProperty ApiIgnore ApiImplicitParam 部分图片来自百…

SpringBoot日志详解

⭐️前言⭐️ &#x1f349;博客主页&#xff1a; &#x1f341;【如风暖阳】&#x1f341; &#x1f349;精品Java专栏【JavaEE进阶】、【JavaEE初阶】、【MySQL】、【数据结构】 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1f601; …

rocketMq相关机制

rocketMq相关机制 topic读写队列 perm字段表示Topic的权限。有三个可选项。 2&#xff1a;禁写禁订阅&#xff0c;4&#xff1a;可订 阅&#xff0c;不能写&#xff0c;6&#xff1a;可写可订阅 这其中&#xff0c;写队列会真实的创建对应的存储文件&#xff0c;负责消息写入。…

小蓝本 第一本《因式分解技巧》第四章 拆项与添项 笔记(第四天)

小蓝本 第一本《因式分解技巧》第四章 拆项与添项 笔记&#xff08;第四天&#xff09;前言拆项与添项目的方法分组分解走平均分配分组分解走瞄准公式旧事重提第二章公式(9)好题习题4题目题解错题题号改错经验前言 芜湖&#xff0c;坚持做小蓝本的第四天&#xff0c;今天的知识…

基于LSTM、BP神经网络实现电力系统负荷预测(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

房屋装修设计技巧有哪些?有哪些注意事项

拥有自己的家是每个人的愿望&#xff0c;拥有一座新的房子是一种幸福。但是&#xff0c;作为一个装修小白&#xff0c;装修新房是一件很麻烦的事情。那么&#xff0c;房屋装修设计技巧是什么&#xff1f;房屋的装修设计应该注意些什么&#xff1f;下面我将详细解释一下。 房屋装…

pandas数据分析

目录 题目001&#xff1a; 把list变成一个Series 题目002&#xff1a; 把dict变成一个Series 题目003&#xff1a; 把Series转换成list 题目004&#xff1a; 把series变成一个DataFrame 题目005&#xff1a;用numpy创建Series 题目006&#xff1a;转换series的数据类型 …

【亲测可用】2022最新酒桌小游戏喝酒小程序源码_带流量主

内容目录一、详细介绍二、效果展示1.部分代码2.效果图展示三、学习资料下载一、详细介绍 喝酒神器3.6&#xff0c;原版本没有广告位&#xff0c;修改增加了广告位&#xff0c; 由多个喝酒小游戏组合而成,具体如下: 大话骰(带音效) 愤怒大叔(带音效,多个皮肤模板用户可选择) …

【大数据入门核心技术-ElasticSearch】(二)ElasticSearch整体架构和重要工作原理

目录 一、整体架构图 二、重要工作原理 1、文档写入原理 2、文档检索原理 一、整体架构 二、重要工作原理 1、文档写入原理 1&#xff09;选择任意一个DataNode发送请求&#xff0c;例如&#xff1a;node2。此时&#xff0c;node2就成为一个coordinating node&#xff08;…

我也和 chatGPT 聊了聊

我也和 chatGPT 聊了聊&#xff0c;都是因为最近 chatGPT 太火了&#xff01; 这是一个大型的 AI 语言模型。你不仅可以和它聊天&#xff0c;问它各种各样的问题&#xff0c;还可以让它写代码、写论文、解数学题、解bug&#xff0c;等等。 可以说&#xff0c;chatGPT 是目前最…

软件安全测试-Web安全测试详解-CSRF攻击

1. 什么是CSRF攻击&#xff1f; CSRF&#xff08;Cross Site Request Forgery&#xff09;&#xff0c;中文是跨站点请求伪造。CSRF攻击者在用户已经登录目标网站之后&#xff0c;诱使用户访问一个攻击页面&#xff0c;利用目标网站对用户的信任&#xff0c;以用户身份在攻击页…

基于java+springmvc+mybatis+jsp+mysql的洗衣店管理系统

项目介绍 洗衣店管理系统是信息时代的产物&#xff0c;它是洗衣店管理的一个好帮手。有了它不再需要繁重的纸质登记&#xff0c;有了它洗衣店管理员不在需要繁重的工作&#xff0c;一些收费标准和干洗业务等基本信息可以由管理人员及时的对信息进行查询、更新、修改和删除&…

【自然语言处理】【ChatGPT系列】大模型的涌现能力

大语言模型的涌现能力《Emergent Abilities of Large Language Models》论文地址&#xff1a;https://arxiv.org/pdf/2206.07682.pdf 相关博客 【自然语言处理】【ChatGPT系列】大模型的涌现能力 【自然语言处理】【文本生成】CRINEG Loss&#xff1a;学习什么语言不建模 【自然…

web前端期末大作业——餐品后台管理系统(html+css+javascript)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

MySQL 日志之 binlog 格式 → 关于 MySQL 默认隔离级别的探讨

背景问题 再讲 binlog 之前&#xff0c;我们先来回顾下主流关系型数据库的默认隔离级别&#xff0c;是默认隔离级别&#xff0c;不是事务有哪几种隔离级别&#xff0c;别会错题意了 1、Oracle、SQL Server 的默认隔离级别是什么&#xff0c;MySQL 的呢 &#xff1f; 2、为什…

基于C#+SQL Server2008 开发三层架构(WinForm)图书管理系统【100010014】

图书管理系统 一、项目背景及意义 当今由于信息技术的飞速发展&#xff0c;图书馆作为社会知识信息媒介的功能日益重要&#xff0c;网络环境下的信息资源建设知识仓库的设计&#xff0c;开放存取学术交流模式&#xff0c;知识管理系统&#xff0c;智能检索&#xff0c;数字参…

SDE论文阅读

论文链接&#xff1a;Score-Based Generative Modeling through Stochastic Differential Equations 文章目录摘要引文背景基于郎之动力学的去噪分数匹配/SMLD去噪扩散概率模型/DDPMSDEs的基于分数的生成模型SDEs下的受扰动数据逆转SDE生成样本估计SDE的分数例子&#xff1a;VE…