容器跨区双向调用的域名注册方案实现
不同网段的容器之间访问存在防火墙,之前在文章Dubbo跨区访问注册IP异常的解决方案已经做过详细的背景介绍了,根本原因在于不同网段的容器服务到注册中心都以本机Host注册和调用,而跨网段之间的访问只能通过Nat-IP进行,以IP注册服务的方式不能满足跨网段的双向调用,最好的解决方案是通过以域名注册的方式,下面就以在工作环境中的真实案例,来验证方案的可行性,从dubbo跨区到MetaQ (Rocket-MQ)都可以进行拓展。
一、Dubbo跨区访问
1.服务提供者申请域名注册
一般来说,服务提供者Provider如果需要满足跨区调用,则需要申请内网域名解析,在同网段解析域名可以得到真实IP,外网段解析该域名的时候能得到Nat-IP。这种线上容器的域名申请一般需要向容器平台或者网络组进行申请,下发域名以后,可以分别在容器内进行验证(IP与域名均已脱敏屏蔽):
#内网容器->解析出真实IP
[wls81@DockerHost ~]$ nslookup
> app-docker-dmz01.doc.demo.com.cn
Server: 215.0.0.1
Address: 215.0.0.1#53
Non-authoritative answer:
Name: app-docker-dmz01.doc.demo.com.cn
Address: 215.0.0.1
#外网容器->解析出 Nat-IP
[wls81@DockerHost ~]$ nslookup
> app-docker-dmz01.doc.demo.com.cn
Server: 30.0.0.1
Address: 30.0.0.1#53
Non-authoritative answer:
Name: app-docker-dmz01.doc.demo.com.cn
Address: 30.0.0.1
2.服务注册
Dubbo注册到ZooKeeper注册中心的Host是可以通过配置文件直接修改的,也有通过修改容器host文件达到目的,但是直接修改环境host也有潜在风险,建议采用配置文件修改的方式,dubbo可以有两种方式:
-
修改
dubbo-context.xml
文件方式:这种方式需要配合修改环境变量信息,现在很少用单点部署的方式了,一般容器环境都是集群部署, 那么所有的实例走完部署后就会共用一份相同dubbo-context.xml
配置,不能写死如下,一旦弹性扩容则每个实例都有自己的独特域名,则无法实现集群注册:
<!--单机版写法,不适合集群-->
<dubbo:protocol name="dubbo" host="app-docker-dmz01.doc.demo.com.cn"
port="20880"/>
上面是单机版的写法,集群部署情况下,配置文件需要采用灵活一点读取本机配置文件的方式,配置值从本机的环境变量中动态获取:
<dubbo:protocol name="dubbo" host="${app.dubbo.config.host}"
port="${app.dubbo.config.port}"/>
可以在全局配置application.properties
文件中分别定义dubbo变量(当然也可以写到JAVA_OPS环境变量中):
app.dubbo.config.host=app-docker-dmz01.doc.demo.com.cn
app.dubbo.config.port=20880
-
修改
dubbo.properties
文件方式:这种方式比上面省略了两个步骤,我们知道Dubbo会自动读取classpath下的名为dubbo.properties
的配置文件,只需要在每个容器实例中添加该文件,并新增如下配置项即可:
dubbo.protocol.host=app-docker-dmz01.doc.demo.com.cn
3.云平台的补充说明
我所在的云平台,因为没有为每个实例单独挂载文件目录,所有的副本都是公用同一份资源空间,如此就导致了集群副本无法差异化自己的个性化配置,只能通过在公共目录下新建实例的IP名目录,提前放好dubbo的配置文件,然后在容器的启动脚本里放上如下程序,在镜像运行后即可将配置文件放在运行目录下生效。
###### get ip ###########################
eth1=`ifconfig |grep -A 2 eth1|grep "inet addr"|awk -F: '{print $2}'|awk '{print $1}'`
if [ -z "$eth1" ]
then
ip_addr_eth1="None"
else
ip_addr_eth1=$eth1
fi
echo $ip_addr_eth1 >/wls/applogs/before.out
###### copy file ###########################
if [ ! -d /middleware/$ip_addr_eth1 ]
then
mkdir -p /middleware/$ip_addr_eth1
chown -R wls81.deploy /middleware/$ip_addr_eth1
fi
echo 'ok1' >/wls/applogs/before.out
if [ -f /middleware/$ip_addr_eth1/dubbo.properties ]
then
\cp -af /middleware/$ip_addr_eth1/dubbo.properties /wls/appsystems/conf/
chown -R wls81.deploy /wls/appsystems/apps/metamorphosis-server-wrapper/conf/
fi
echo 'ok2' >/wls/applogs/before.out
4.Zookeeper查看服务注册信息
修改完成后都需要重启容器,dubbo就会加载这部分配置信息到Zookeeper上注册服务,有两种方式可以检查服务信息:
- 通过dubbo-admin管理后台查看服务信息,服务注册的url中可以看到host信息已经成功注册了:
- 如果没有安装dubbo-admin后台,也可以通过ZooKeeper客户端命令查看dubbo服务提供者信息:
[zk: localhost:2181(CONNECTED) 14] ls2 /dubbo/com.paic.mo.dubbo.biz.service.PecpDubboService/providers
dubbo://app-docker-dmz01.doc.demo.com.cn:28080/com.paic.mo.dubbo.biz.service.PecpDubboService?
application=app&dubbo=2.4.10&group=pasc&interface=com.demo.dubbo.biz.service.PecpDubboService&
methods=sendMail&pid=471&revision=1.0.0&side=provider&timeout=3000×tamp=1563542682061&version=1.0.0
cZxid = 0x600015f3f
ctime = Wed Jul 17 17:36:06 CST 2019
mZxid = 0x600015f3f
mtime = Wed Jul 17 17:36:06 CST 2019
pZxid = 0x600023b18
cversion = 81
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1
[zk: localhost:2181(CONNECTED) 15]
二、MetaQ
1.Broker申请域名注册
此步骤同上完全一致,只不过申请域名的对象由服务提供者转变为消息中间件的Broker,因为应用同MQ交互的是Broker角色。
2.服务注册
如果是早起的MetaQ版本,注册域名很简单只需要在server.ini
文件中添加本机的域名信息即可:
[wls81@DockerHost]$ vi server.ini
[system]
brokerId=0
hostName=metaq-broker1-01.doc.demo.com.cn
numPartitions=4
serverPort=8123
如果是RocketMQ,注册域名的方式则需要在broker.properties
文件中修改配置项如下即可:
[wls81@DockerHost]$ vi broker.properties
namesrvAddr=ip:port;
brokerIP1=rocketmq-broker1-01.doc.demo.com.cn
3.应用查看注册信息
应用在运行与重启都会从zk中拉取到metaq-broker的信息,如果能看到日志中rebalance到域名下的broker节点信息,同样可以验证MQ类型的MQ调用是正常可用了,如果域名解析失败或者防火墙不通,容器都不会健康启动,或者会在启动日志里打印出连接broker的异常堆栈信息的。
[DefaultLoadBalanceStrategy] - Consumer app rebalancing the following partitions: [0-0, 0-1, 0-2, 0-3] for
topic metaq_test with consumers: [app-1, app-2]
[ConsumerZooKeeper] - app-2 attempting to claim partition 0-2
[ConsumerZooKeeper] - app-2 attempting to claim partition 0-3
[ConsumerZooKeeper] - Connected to meta:metaq-broker1-01.doc.demo.com.cn//:8123
[ConsumerZooKeeper] - Starting fetch runners
[ConsumerZooKeeper] - end rebalancing consumer app-2 try #0
[ConsumerZooKeeper] - rebalance success.
[MessageListenerContainer] - Initialize message listener container successfully.