Docker容器http请求限制

我是Docker的新手,所以很可能我错过了一些东西。

我用Elasticsearch运行一个容器,使用这个图像 。

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

问题是,这些请求中的很多请求都卡住了,直到失败。 如果我做netstat -tn | grep 9200 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 

有很多要求。 在这一点上,我不确定是否是弹性search或docker相关的东西。 如果Elasticsearch在我的机器上是instaleld,则不会发生这种情况。

一些信息:

 $ 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和Elastic都不是问题。 回顾一下,在Elasticsearch安装程序中抛出PUT请求的同一脚本在本地工作,但是在几千个文档(20k)之后抛出在Elasticsearch的容器上失败。 要注意的是,这个文件总数已经达到了800k。

那么,发生了什么? 当你在本地主机上运行somethig并向它发出一个请求时(在这种情况下是一个PUT请求),这个请求就会通过loopback接口。 在实践中,这意味着没有TCP连接创造更快的速度。

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

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

这实际上是一个更现实的情况。 我们在另一台机器上设置Elasticsearch,并做了完全相同的testing,并得到了相同的结果。

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

三个build议来解决这个问题:

  1. 每隔一段时间暂停一次请求。 也许每隔X个请求就可以睡一觉,TIME_WAIT可以通过,连接closures
  2. 发送Connection: close header:选项,发件人发出信号表示完成响应后连接将被closures。
  3. 重用连接。

我结束了与选项3),并重写了我的同事的脚本,并重新使用相同的TCP连接。