端口与服务端口的区别是什么?

6

在探索马拉松REST API时,我发现在以下API调用的信息(JSON输出)中定义了两个端口号(ports和service ports)-
curl http://x.y.z.w:8080/v2/tasks | python -m json.tool | less
示例输出如下:

{
  "tasks":[
    {
      "appId":"/test",
      "host":"172.20.75.145",
      "id":"test.1fc922a9-f4c8-11e5-8bff-005056a76a7f",
      "ipAddresses":[

      ],
      "ports":[
        31313
      ],
      "servicePorts":[
        10000
      ],
      "slaveId":"2130f59b-7289-40eb-b24d-72f0c6fe94c8-S1",
      "stagedAt":"2016-03-28T09:33:26.859Z",
      "startedAt":"2016-03-28T09:33:26.936Z",
      "version":"2016-03-28T09:33:26.800Z"
    }
  ]
}

这里的ports和servicePorts有什么区别呢?请添加更多信息。


你已经阅读了 https://mesosphere.github.io/marathon/docs/ports.html 上的文档吗? - Michael Hausenblas
1
我已经阅读了它,但由于对HAproxy的探索较少,我无法准确理解服务端口的必要性。您能否以非技术性的方式解释一下? - Yogesh Jilhawar
如果您发现其中一个答案有用,请将问题标记为已回答。谢谢! - Brian Topping
2个回答

11
根据Marathon文档:
servicePort: 当你在Marathon中创建一个新应用程序(通过REST API或前端),你可以为其分配一个或多个服务端口。你可以指定所有有效的端口号作为服务端口,也可以使用0来表示Marathon应自动为应用程序分配免费的服务端口。如果你选择自己的服务端口,你必须确保它在你所有应用程序中是唯一的。
让我在Marathon的两种主要网络配置的情况下详细解释一下,并在此过程中提供一些有关它们的信息。
主机模式
用途:Docker应用程序的默认选项,非Docker应用程序的唯一选项
在这种配置下,你的应用程序将直接绑定到主机的端口上。
如果不使用服务端口
你可以要求Marathon为你提供主机的任意两个端口,与你想要为应用程序提供的端口相同。在应用程序配置文件中有两种方法可以实现这一点:
"ports": [
    0, 0
],

或者

"portDefinitions": [
      {"port": 0}, {"port": 0}
],

通过这样做,Marathon将从可用端口范围中保留两个端口,并将它们分配给环境变量PORT1PORT2。然后,在您的Dockerfile中直接调用它们非常容易:
CMD ./launch.sh --listen-on $PORT1 --monitor-on $PORT2

或者在您的Marathon配置中的cmd定义中:

"cmd": "./launch.sh --listen-on $PORT1 --monitor-on $PORT2"

使用服务端口

假设您在多台主机上运行应用程序(运行多个实例),并且希望能够连接到特定端口上任何主机上的应用程序。这就是服务端口发挥作用的时候。
通过在配置文件中编写:

"ports": [
    3000, 3001
],

或者:

"portDefinitions": [
    {"port": 3000}, {"port": 3001}
],

马拉松仍然会在主机上分配随机端口,仍然会将它们分配给环境变量PORT1PORT2,并且还会为您保留3000和3001端口供您使用。

由您决定使用服务发现机制将流量从这些服务端口路由到$PORT1$PORT2

您可以使服务端口等于主机端口(例如,如果您想避免使用服务发现机制)并在不同主机上为您的应用程序使用一致的端口。您可以在端口规范后添加"requirePorts": true来实现此目的。
这里的警告是,Marathon只能在具有这些端口的节点中调度您的应用程序。

桥接模式

用途:仅限Docker应用程序

在此配置下,指定的一些容器端口绑定到主机端口。

不使用服务端口

在此模式下,您不使用“ports”或“portDefinitions”指令,而是使用“portMappings”。通过这样做,您有效地告诉Docker将特定容器端口的流量映射到主机端口,反之亦然。

您可以通过指定以下内容将容器端口映射到主机端口:

"portMappings": [
    { "containerPort": 80, "hostPort": 0, "protocol": "tcp"},
    { "containerPort": 443, "hostPort": 0, "protocol": "tcp"}
]

在这种情况下:
- 将hostPort设置为0会使它再次从可用端口范围中选择一个随机端口。同样,这些端口分别分配给PORT1PORT2环境变量。
- 将containerPort设置为0将使其等于hostPort

使用服务端口

与之前一样,您可以通过在配置中指定它们来启用服务端口,这样它们将在主机之间保持一致:

"portMappings": [
    { "containerPort": 80, "hostPort": 0, "protocol": "tcp", "servicePort": 3000},
    { "containerPort": 443, "hostPort": 0, "protocol": "tcp", "servicePort": 3001}
]

再次提醒您,需使用服务发现机制将流量路由到这些服务端口的$PORT1$PORT2

更多信息请参见:

Marathon 端口: https://mesosphere.github.io/marathon/docs/ports.html
Docker 主机模式: http://www.dasblinkenlichten.com/docker-networking-101-host-mode/
Docker 桥接模式: http://www.dasblinkenlichten.com/docker-networking-101/


在你的Docker示例中,这是否意味着人们将能够通过3000和3001端口访问服务? - Dimitri Kopriwa

3

基本上,通过服务端口,Marathon告诉Haproxy(或服务发现),你监听这个端口,我会提供我的实例主机IP和端口列表,你必须将流量路由到这里。而haproxy使用自己的路由算法在实例列表中分发流量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接