概要
Dockerのコンテナ間通信の方法として
- Container Link
- Volume経由のUnix Domain Socket
といった方法がありますが、どっちの方が速いのか調べてみました
TL;DR
Unix Domain Socketの方が速い
※当環境だと 8%程度
検証環境
- Sinatra+Unicornが動くコンテナを作成、TCP:8080とUnix Domain SocketにてListen
- NginxなコンテナからTCP:8080とUnix Domain SocketをUpstream指定
上記環境に対し、ApacheBenchで -c 10 -n 10000
を3回実行、平均で比較
NEC LaViE G Type Z
Intel(R) Core(TM) i7-4500U CPU @ 1.80GHz
MemTotal: 3966364 kB
Disk: Model=SAMSUNG MZMTD256HAGM-000L1
Ubuntu 14.04
ruby 2.2.2p95
※詳細は後ほど
結果
$ ab -n 10000 -c 100 http://172.17.0.104/tcp
Requests per second: 2382.71 [#/sec] (mean)
Time per request: 41.969 [ms] (mean)
Requests per second: 2348.47 [#/sec] (mean)
Time per request: 42.581 [ms] (mean)
Requests per second: 2349.65 [#/sec] (mean)
Time per request: 42.560 [ms] (mean)
$ ab -n 10000 -c 100 http://172.17.0.104/uds
Requests per second: 2574.83 [#/sec] (mean)
Time per request: 38.837 [ms] (mean)
Requests per second: 2538.66 [#/sec] (mean)
Time per request: 39.391 [ms] (mean)
Requests per second: 2554.32 [#/sec] (mean)
Time per request: 39.149 [ms] (mean)
8%程度、Unix Domain Socketの方が速い
詳細
下記を全て行うと http://NGINX_CONTAINER/tcp
と http://NGINX_CONTAINER/uds
というURLができあがり、それぞれTCP経由、Unix Domain Socket経由でSinatra+Unicornへアクセスします
Sinatra+Unicorn Dockerコンテナ(HTTPd)
FROM ubuntu:latest
MAINTAINER Kohei MATSUSHITA <ma2shita+git@ma2shita.jp>
RUN apt-get update
RUN apt-get install -y software-properties-common
RUN apt-add-repository -y ppa:brightbox/ruby-ng
RUN apt-get update
RUN apt-get install -y --no-install-recommends build-essential vim curl git ssh-client supervisor unzip rsync lsof ruby2.2 ruby2.2-dev libpq-dev
RUN apt-get clean
RUN gem install bundle rake --no-rdoc --no-ri
COPY . /tmp/sinatra/
WORKDIR /tmp/sinatra/app/
RUN bundle install
EXPOSE "8080"
CMD ["bundle", "exec", "unicorn", "-c", "./unicorn.rb"]
source "https://rubygems.org"
gem "sinatra"
gem "unicorn"
require "rubygems"
require "sinatra/base"
class HelloApp < Sinatra::Base
get "/" do
"Ok!!"
end
get "/uds" do
"hello"
end
get "/tcp" do
"hello"
end
end
run HelloApp
worker_processes 4
listen "0.0.0.0:8080"
Dir.mkdir "/dev/shm/unicorn/" rescue nil
listen "/dev/shm/unicorn/io.sock"
stderr_path "/dev/null"
stdout_path "/dev/null"
docker build & run
上記を用意した上で下記を実行
$ docker build --force-rm --tag sinatra .`
$ docker run --name sinatra --rm -v ${PWD}/unicorn.io:/dev/shm/unicorn sinatra
※${PWD}/unicorn.io/
に io.sock
というUnix Domain Socketができる(待ち受けている)
Nginx
NginxはofficialのDocker imageを使用するため、Dockerfileは作りません
upstream uds_backend {
server unix:/dev/shm/unicorn/io.sock;
}
upstream tcp_backend {
server 172.17.0.103:8080;
}
server {
access_log /dev/null;
listen 80;
server_name _;
location /uds {
proxy_pass http://uds_backend;
}
location /tcp {
proxy_pass http://tcp_backend;
}
}
※tcp_backend
の server アドレスは、先に起動した sinatra コンテナのIPアドレスを書きます。docker inspect httpd
で調べてください
docker run
$ docker run --name rproxy --link httpd:httpd -v ${PWD}/unicorn.io:/dev/shm/unicorn -v ${PWD}/nginx_conf.d:/etc/nginx/conf.d -p 80:80 --rm nginx
※${PWD}/unicorn.io
は sinatra コンテナで指定したディレクトリと同じものを指定する必要があります (io.sock
を共有)
あとがき
- Volumeを使う場合、同一ホストである事が必須となってしまうので、そういうアプリケーションには良いかもしれない (nginxのように環境変数を読ませるのにTIPSが必要な状況下なら、なおさらgoodかもしれない)
こういうことができる人、本当に募集してます
いそがしい