【问题标题】:Docker container http requests limitDocker 容器 http 请求限制
【发布时间】:2015-06-15 08:43:16
【问题描述】:

我是 Docker 新手,所以很可能我遗漏了一些东西。

我正在用 Elasticsearch 运行一个容器,使用这个 image

我能够正确设置一切。之后,我使用了一个同事开发的脚本来插入一些数据,基本上是查询 MySQL 数据库并发出 HTTP 请求。

问题是,其中许多请求会一直卡住,直到失败。如果我这样做netstat -tn | grep 9200,我会得到:

tcp6       0      0 ::1:58436               ::1:9200                TIME_WAIT  
tcp6       0      0 ::1:59274               ::1:9200                TIME_WAIT 

...
tcp6       0      0 ::1:58436               ::1:9200                TIME_WAIT  
tcp6       0      0 ::1:59274               ::1:9200                TIME_WAIT 

有很多请求。在这一点上,我不确定它是否与弹性搜索或 docker 有关。如果在我的机器上安装了 Elasticsearch,则不会发生这种情况。

一些信息:

$ docker version
Client version: 1.6.2
Client API version: 1.18
Go version (client): go1.4.2
Git commit (client): 7c8fca2
OS/Arch (client): linux/amd64
Server version: 1.6.2
Server API version: 1.18
Go version (server): go1.4.2
Git commit (server): 7c8fca2
OS/Arch (server): linux/amd64

$ docker info
Containers: 6
Images: 103
Storage Driver: devicemapper
 Pool Name: docker-252:1-9188072-pool
 Pool Blocksize: 65.54 kB
 Backing Filesystem: extfs
 Data file: /dev/loop0
 Metadata file: /dev/loop1
 Data Space Used: 4.255 GB
 Data Space Total: 107.4 GB
 Data Space Available: 103.1 GB
 Metadata Space Used: 6.758 MB
 Metadata Space Total: 2.147 GB
 Metadata Space Available: 2.141 GB
 Udev Sync Supported: false
 Data loop file: /var/lib/docker/devicemapper/devicemapper/data
 Metadata loop file: /var/lib/docker/devicemapper/devicemapper/metadata
 Library Version: 1.02.82-git (2013-10-04)
Execution Driver: native-0.2
Kernel Version: 3.14.22-031422-generic
Operating System: Ubuntu 14.04.2 LTS
CPUs: 4
Total Memory: 15.37 GiB

$ docker logs elasticsearch
[2015-06-15 09:10:33,761][INFO ][node                     ] [Energizer] version[1.6.0], pid[1], build[cdd3ac4/2015-06-09T13:36:34Z]
[2015-06-15 09:10:33,762][INFO ][node                     ] [Energizer] initializing ...
[2015-06-15 09:10:33,766][INFO ][plugins                  ] [Energizer] loaded [], sites []
[2015-06-15 09:10:33,792][INFO ][env                      ] [Energizer] using [1] data paths, mounts [[/usr/share/elasticsearch/data (/dev/mapper/ubuntu--vg-root)]], net usable_space [145.3gb], net total_space [204.3gb], types [ext4]
[2015-06-15 09:10:35,516][INFO ][node                     ] [Energizer] initialized
[2015-06-15 09:10:35,516][INFO ][node                     ] [Energizer] starting ...
[2015-06-15 09:10:35,642][INFO ][transport                ] [Energizer] bound_address {inet[/0:0:0:0:0:0:0:0:9300]}, publish_address {inet[/172.17.0.5:9300]}
[2015-06-15 09:10:35,657][INFO ][discovery                ] [Energizer] elasticsearch/Y1zfiri4QO21zRhcI-bTXA
[2015-06-15 09:10:39,426][INFO ][cluster.service          ] [Energizer] new_master [Energizer][Y1zfiri4QO21zRhcI-bTXA][76dea3e6d424][inet[/172.17.0.5:9300]], reason: zen-disco-join (elected_as_master)
[2015-06-15 09:10:39,446][INFO ][http                     ] [Energizer] bound_address {inet[/0:0:0:0:0:0:0:0:9200]}, publish_address {inet[/172.17.0.5:9200]}
[2015-06-15 09:10:39,446][INFO ][node                     ] [Energizer] started
[2015-06-15 09:10:39,479][INFO ][gateway                  ] [Energizer] recovered [0] indices into cluster_state

脚本的重要部分:

for package in c.fetchall():
    id_package, tracking_number, order_number, payment_info, shipment_provider_name, package_status_name=package
    el['tracking_number'] = tracking_number
    el['order_number'] = order_number
    el['payment_info'] = payment_info
    el['shipment_provider_name'] = shipment_provider_name
    el['package_status_name'] = package_status_name

    requests.put("http://localhost:9200/packages/package/%s/_create"%(id_package), json=el)

【问题讨论】:

  • 请包含进行调用的脚本以及docker logs yourContainer的输出。
  • 你应该观察 'docker ps -a' 的输出,看看它是否正在运行以及哪些端口绑定到容器
  • 使用所需信息编辑问题。我只绑定了 9200 端口,但再次尝试绑定 9200-9300 并得到相同的结果。

标签: http elasticsearch docker


【解决方案1】:

因此,Docker 或 Elastic 都不是问题。回顾一下,在 Elasticsearch 设置中抛出 PUT 请求的相同脚本在本地工作,但是在使用 Elasticsearch 的容器中抛出数千个文档(20k)后失败。需要注意的是,文档的总数大约是 800k。

那么,发生了什么?当您设置在 localhost 上运行的某些东西并向其发出请求(在本例中为 PUT 请求)时,该请求将通过环回接口。在实践中,这意味着没有创建 TCP 连接,从而加快了速度。

设置 docker 容器时,端口已绑定到主机。尽管脚本仍然在所需端口上向 localhost 发出请求,但通过 docker0 接口在主机和 docker 容器之间创建了 TCP 连接。这是以两件事为代价的:

  • 建立 TCP 连接的时间
  • TIME_WAIT 状态

这实际上是一个更现实的场景。我们在另一台机器上设置了 Elasticsearch 并进行了完全相同的测试,并得到了与预期相同的结果。

问题是我们正在发送请求并为每个请求创建一个新连接。由于 TCP 的工作方式,连接不能立即关闭。这意味着我们一直在使用所有可用的连接,直到没有可用的连接,因为创建速度高于实际关闭速度。

解决此问题的三个建议:

  1. 每隔一段时间暂停一次请求。也许在每个 X 请求时休眠,以便 TIME_WAIT 通过并关闭连接
  2. 发送Connection: close 标头:发送方的选项,表示响应完成后连接将关闭。
  3. 重复使用连接。

我最终选择了选项 3)并重写了我同事的脚本并重用了相同的 TCP 连接。

【讨论】:

    猜你喜欢
    • 2016-12-27
    • 1970-01-01
    • 2023-02-07
    • 1970-01-01
    • 2014-08-19
    • 1970-01-01
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    相关资源
    最近更新 更多