2015-06-15 141 views
4

我是新來的Docker,所以很可能我錯過了一些東西。碼頭集裝箱http請求限制

我使用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在我的機器上出現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) 
+0

請包括進行調用的腳本以及'docker logs yourContainer'的輸出。 – L0j1k

+0

喲應該觀看'docker ps -a'的輸出以查看它是否正在運行以及哪些端口綁定到容器上 – Andrea

+0

用所需的信息編輯問題。我只綁定了9200端口,但通過綁定9200-9300再次嘗試並得到相同的結果。 – rmcc

回答

2

所以,這不符合任何碼頭工人或彈性的問題。回想一下,在本地Elasticsearch設置中拋出PUT請求的相同腳本可以工作,但是在使用Elasticsearch的容器拋出幾千個文檔(20k)後,拋出該腳本失敗。要注意的是,整個文件數量是800k。

那麼,究竟發生了什麼?當你在localhost上運行somethig並向它發出一個請求時(在這種情況下是一個PUT請求),這個請求會通過loopback接口。在實踐中,這意味着沒有TCP連接被創建使得速度更快。

設置碼頭容器時,端口綁定到主機。雖然腳本仍然在所需端口上向本地主機發出請求,但通過docker0接口在主機和docker容器之間創建TCP連接。這都在兩件事情的費用:

  • 時間設置一個TCP連接
  • TIME_WAIT狀態

這實際上是一個更現實的情況。我們在另一臺機器上設置了Elasticsearch,並做了完全相同的測試,並按預期得到了相同的結果。

問題是我們正在發送請求,併爲他們每個人創建一個新的連接。由於TCP的工作方式,連接不能立即關閉。這意味着我們正在使用所有可用的連接,直到我們沒有人使用,因爲創建率高於實際關閉率。

三點建議解決這一問題:

  1. 暫停請求,在每過一段時間。也許在每個X請求中都可以休眠,以使TIME_WAIT可以通過並且連接關閉
  2. 發送Connection: close標頭:發件人選項可以表示在完成響應後連接將被關閉。
  3. 重用連接(s)。

我結束了與選項3)並重寫我的同事的腳本並重新使用相同的TCP連接。