hi,你好!欢迎访问本站!登录
本站由网站地图腾讯云宝塔系统阿里云强势驱动
当前位置:首页 - 教程 - 杂谈 - 正文 君子好学,自强不息!

Dubbo与Kubernetes集成

2019-11-18杂谈搜奇网36°c
A+ A-

Dubbo运用迁移到docker的题目

Dubbo是阿里开源的一套效劳治理与rpc框架,效劳的供应者经由历程zookeeper把本身的效劳宣布上去,然后效劳挪用方经由历程zk猎取效劳的ip和端口,dubbo客户端经由历程本身的软负载功用自动挑选效劳供应者并挪用,全部历程牵涉到的三方关联以下图所示。

在一般的情况下,这三方都在同一个互通的网段,provider供应给zk的就是猎取到的本机地点,consumer能接见到这个地点。

然则假如效劳放在docker容器中,而挪用者并不在docker中,它们的网段是不一样的。

这个时刻就出现题目了,consumer无法接见到provider了。

Dubbo供应的处理方案

新版的Dubbo供应了四个设置来指定与注册效劳相干的地点和端口。

DUBBO_IP_TO_REGISTRY: 要宣布到注册中心上的地点
DUBBO_PORT_TO_REGISTRY: 要宣布到注册中心上的端口
DUBBO_IP_TO_BIND: 要绑定的效劳地点(监听的地点)
DUBBO_PORT_TO_BIND: 要绑定的效劳端口

以IP地点为例,Dubbo先找是否是有DUBBO_IP_TO_BIND这个设置,假如有运用设置的地点,假如没有就取本机地点。然后继承找DUBBO_IP_TO_REGISTRY,假如有了设置,运用设置,不然就运用DUBBO_IP_TO_BIND。详细代码以下:

        /**
         * 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 static String findConfigedHosts(ServiceConfig<?> sc,
                                                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 (sc.getProvider() != null && StringUtils.isEmpty(hostToBind)) {
                    hostToBind = sc.getProvider().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;
        }

然后我们看这个getValueFromConfig(),它挪用了下面的函数,能够看到,它是先找环境变量,再找properties。

    public static String getSystemProperty(String key) {
        String value = System.getenv(key);
        if (StringUtils.isEmpty(value)) {
            value = System.getProperty(key);
        }
        return value;
    }

所以我们经由历程环境变量,就可以修正Dubbo宣布到zookeeper上的地点和端口。假如我们经由历程docker镜像启动了一个dubbo provider,而且它的效劳端口是8888,假定主机地点为192.168.1.10,那末我们经由历程下面的敕令,

docker run -e DUBBO_IP_TO_REGISTRY=192.168.1.10 -e DUBBO_PORT_TO_REGISTRY=8888 -p 8888:8888 dubbo_image

就可以让内部的效劳以192.168.1.10:8888的地点宣布。

我们经由历程官方的实例来演示一下,由于官方供应的案例都很久了,所以我本身从新搞了一个示例,代码在https://github.com/XinliNiu/dubbo-docker-sample.git 。

先启动一个zookeeper,暴露2181端口。

docker run --name zkserver --rm -p 2181:2181  -d zookeeper:3.4.9

看一下zk起来了

niuxinli@niuxinli-B450M-DS3H:~/dubbo-samples-docker$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                         NAMES
5efc1f17fba0        zookeeper:3.4.9     "/docker-entrypoint.…"   4 seconds ago       Up 2 seconds        2888/tcp, 3888/tcp, 0.0.0.0:2181->2181/tcp   zkserver

把代码导入IDE,修正dubbo-docker-provide.xml,把地点改成刚宣布到zk的地点和端口,我的地点是192.168.1.8。

运转DubboApplication,这时刻能够看到在zk上注册了效劳。

修正dubbo-docker-consumer.xml里的zk地点,实行单元测试,能一般接见。

把DubboApplication导出成能够实行的jar包,名字叫app.jar,建立以下Dockerfile

FROM openjdk:8-jdk-alpine
ADD app.jar app.jar
ENV JAVA_OPTS=""
ENTRYPOINT exec java $JAVA_OPTS -jar /app.jar

建立dubbo-demo镜像,在一样的目次里实行docker build。

docker build --no-cache -t dubbo-demo .

一般启动镜像

docker run  -p 20880:20880  -it --rm dubbo-demo

发现是172.16.0.3的地点,这个是接见不了的。

传入环境变量从新启动,

docker run  -e DUBBO_IP_TO_REGISTRY=192.168.1.8 -e DUBBO_PORT_TO_REGISTRY=20880 -p 20880:20880  -it --rm dubbo-demo

这时刻就变成主机地点了。

docker run --name zkserver --rm -p 42181:2181  -d zookeeper:3.4.9

看一下zk起来了

niuxinli@niuxinli-B450M-DS3H:~/docker_dubbo_demo/dubbo-samples/dubbo-samples-docker$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                         NAMES
5efc1f17fba0        zookeeper:3.4.9     "/docker-entrypoint.…"   4 seconds ago       Up 2 seconds        2888/tcp, 3888/tcp, 0.0.0.0:42181->2181/tcp   zkserver

如今启动dubbo provider,运用link的体式格局衔接zk,我的本机地点是192.168.1.8,provider本身暴露的端口为20880,主机暴露端口改成28888。

在Kubernetes中运用Dubbo

当在Kubernetes中启动多个副本的时刻,指定详细的IP和详细的端口,都是不可行的,由于每一个机械的IP都不一样,不能写很多个yaml文件,而且一旦指定了详细端口,那这台主机的这个端口就被占用了。

我们能够经由历程建立Service,运用NodePort的体式格局,把端口牢固住,如许端口的题目就处理了。由于是对外效劳,所以运用ClusterIP肯定是不行了,IP有两种处理方法:

(1)运用Kubernetes的downward api动态的传入主机的ip。

(2)传牢固的loadbalancer的地点,比方在所有的node以外有一个F5。

不论哪一种要领,都是一种让步的方法,很不“云原生”,我演示一下运用downward api动态传入主机地点,并运用nodeport牢固端口的体式格局。

我的kubernetes集群以下:

角色 地点
master 192.168.174.50
node1 192.168.174.51
node2 192.168.174.52
node3 192.168.174.53

zk的地点是192.168.1.8,它与集群的主机互通。

我没有建private镜像堆栈,把我之前打好的dubbo-demo直接push到docker-hub上了,名字是nxlhero/dubbo-demo。

建立Service,运用的NodePort为30001,建立4个副本,如许3台机械上正好有一台起两个pod。

apiVersion: v1
kind: Service
metadata:
  name: dubbo-docker
  labels:
    run: dubbo
spec:
  type: NodePort
  ports:
  - port: 20880
    targetPort: 20880
    nodePort: 30001
  selector:
    run: dubbo-docker
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dubbo-docker
spec:
  selector:
    matchLabels:
      run: dubbo
  replicas: 4
  template:
    metadata:
      labels:
        run: dubbo
    spec:
      containers:
      - name: dubbo-docker
        image: nxlhero/dubbo-demo
        env:
        - name: DUBBO_IP_TO_REGISTRY
          valueFrom:
            fieldRef:
              fieldPath: status.hostIP
        - name: DUBBO_PORT_TO_REGISTRY
          value: "30001"
        tty: true
        ports:
        - containerPort: 20880

这个yaml最症结的处所就是环境变量,主机IP经由历程downward apid传入,端口运用牢固的nodeport。

        env:
        - name: DUBBO_IP_TO_REGISTRY
          valueFrom:
            fieldRef:
              fieldPath: status.hostIP
        - name: DUBBO_PORT_TO_REGISTRY
          value: "30001"

建立Service,启动后能够看到zookeeper上的地点都是主机的地点和nodeport。

  选择打赏方式
微信赞助

打赏

QQ钱包

打赏

支付宝赞助

打赏

  移步手机端
Dubbo与Kubernetes集成

1、打开你手机的二维码扫描APP
2、扫描左则的二维码
3、点击扫描获得的网址
4、可以在手机端阅读此文章
未定义标签

本文来源:搜奇网

本文地址:https://www.sou7.cn/282243.html

关注我们:微信搜索“搜奇网”添加我为好友

版权声明: 本文仅代表作者个人观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。请记住本站网址https://www.sou7.cn/搜奇网。

发表评论

选填

必填

必填

选填

请拖动滑块解锁
>>