Docker Swarm系列——7.Swarm服务调用

文章目录

        • 1. 网络名称
        • 2. 服务名称

在这篇文章中,大家将会了解在Swarm中,服务与服务之间如何互相调用。通过前面几篇文章的学习,我们已经能够熟练地部署服务,并在浏览器中成功访问。但是,我们一直以来部署的都是单个服务,还没接触到例如,在 web中调用 api,在 api中调用 mysql,接下来,我们就从网络开始,一探究竟。

1. 网络名称

还记得我们最开始通过docker network create -d overlay --attachable httpnet创建的httpnet网络吗?这一步究竟做了什么?如果不清楚,docker教给我们一个方法inspect

$ docker network inspect httpnet

[
...
    {
        "Name": "httpnet",
        "IPAM": {
            "Config": [
                {
                    "Subnet": "10.0.1.0/24",
                    "Gateway": "10.0.1.1"
                }
            ]
        },
...
    }
]

我们只截取了对网络httpnet分析最重要的一部分,仔细看一下,我们会发现如下新的信息:

  • Subnet子网,凡是注册到此网络上的服务或容器,docker都会从10.0.1.0/24中自动分配一个或多个内部IP给它。
  • Gateway网关,httpnet网络的网关是10.0.1.1

默认在同一个子网(内网),任何IP都可以ping通,任何PORT都对外开放,这就是本质上容器间或服务间互相访问调用的方式。

2. 服务名称

我们已经知道,本质上容器间或服务间都是通过ip:port的形式进行访问或调用,但是我们同时也清楚,容器的生命周期始于创建终于销毁,且容器的启停很频繁,那就意味着一个服务中容器的真实IP随时都可能改变。

因此,docker提供给我们的方式,通过命令的编写就能看出来,那就是名称,包括网络名称、stack名称、服务名称、容器名称等。那让我们看看,服务名称背后又是什么玄机?

$ docker service inspect http-v1

[
...
        "Spec": {
            "Name": "http-v1",
            "Networks": [
                {
                    "Target": "httpnet"
                }
            ],
            "Replicated": {
                    "Replicas": 2
                }
        }
        "Endpoint": {
            "Spec": {
                "Mode": "vip",
                "Ports": [
                    {
                        "Protocol": "tcp",
                        "TargetPort": 80,
                        "PublishedPort": 80,
                        "PublishMode": "ingress"
                    }
                ]
            },
            "VirtualIPs": [
                {
                    "NetworkID": "m8hsd6mdesxey1m0sm6ipjxrt",
                    "Addr": "10.0.1.7/24"
                }
            ]
...
    }
]

我们只截取了对服务http-v1分析最重要的一部分,仔细看一下,我们会发现如下新的信息:

  • Mode机制,vip代表对服务中所有容器的代理,不是直接访问,而是通过vip地址。
  • Addr地址,vip的地址为10.0.1.7,它代表服务的地址,但不是真实的容器地址。

我们可以任意进入一个容器里面看看:

$ docker exec -it http-v1.2.7xp9liu4tn21hzogtqhyswk5n /bin/sh

# traceroute http-v1
traceroute to http-v1 (10.0.1.7), 30 hops max, 46 byte packets
 1  10.0.1.7 (10.0.1.7)  0.029 ms  0.672 ms  0.024 ms
 
# curl http-v1
{"version":"v1","hostname":"6e54dd2e8007","address":"10.0.1.9"}/app

# curl http-v1
{"version":"v1","hostname":"4d51a5226238","address":"10.0.1.8"}/app

# curl 10.0.1.7
{"version":"v1","hostname":"6e54dd2e8007","address":"10.0.1.9"}/app

# curl 10.0.1.7
{"version":"v1","hostname":"4d51a5226238","address":"10.0.1.8"}/app

在这里插入图片描述
不难看出,一个服务永远只对应一个VIP,而VIP通过轮询每次返回一个真实的容器IP,且VIP负责维护真实容器的所有IP(创建、销毁)。
在这里插入图片描述
此外,如果一个服务对外暴露了端口,也可以通过外部ip:port的方式进行调用。但是这种方式不仅舍近求远,还增加了IP地址转换的性能损耗,而且因为集群中每个节点的ip:port都可以访问,那该选择一个固定的还是每次从所有的节点中随机?如果一个节点不可用又怎么办?

至此,我们终于弄明白了在【2.Swarm服务发现】文章中未深入介绍的服务发现和负载均衡原理,同时,如果在一个服务中想要调用另外一个服务,只需要在连接字符串中加入另外一个服务的名称和端口即可。

你可能感兴趣的:(docker)