h2oを試してみる

最近、高速なサーバーソフトウェアとしてh2oを耳にするので試してみました。

https://github.com/h2o/h2o


結論から言うと高速でした。Ubuntu@Opteron3280で約16万req/sec以上出ています。今まで計測した中で最速で、OpenRestyより早いと思います。計測マシンの方がCPUを使いきって計測しきれませんでしたので、もっと出ると思います。

インストール方法を最初に書いておきます。ubuntuです。

# いろいろとインストール。これだけでは足りないと思います、OpenSSLとか必要かもです、適宜入れて下さい
$ aptitude install cmake make gcc c++ libyaml-dev
$ git clone git clone https://github.com/h2o/h2o
$ cmake .
$ make

# confを編集。コンフィグ例をこの記事の下の方に置いておきました
$ vi examples/h2o/h2o.conf

# index.htmlを編集します
$ echo '<p>Hello, This is h2o!</p>' > examples/doc_root/index.html 

# 動かします
$ ./h2o -c examples/h2o/h2o.conf
h2o server (pid:10204) is ready to serve requests

ベンチマークをしてみます。wrkというベンチマークツールを使います。これのインストール方法や使い方は検索して下さい。

↑のマシン(192.168.1.2とします)と、GbEスイッチングハブで繋いだ別マシンから計測してみます。

トポロジーは、

Ubuntu@Opteron3280 (8コアCPU、IP ADDR: 192.168.1.2)
|
GbEスイッチングハブ
|
Debian@Pentium Dual-Core E5200 (2コアCPU、IP ADDR: 192.168.1.118)

です。

# まずはきちんとアクセス出来るか確認
$ curl http://192.168.1.2:8080/
<p>Hello, This is h2o!</p>

# wrkベンチマーク (同時接続500、10スレッド、10秒間の計測)
$ ./wrk -c 500 -t 10 -d 10 http://192.168.1.2:8080/
Running 10s test @ http://192.168.1.2:8080/
  10 threads and 500 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     9.04ms   63.59ms 661.01ms   98.38%
    Req/Sec    16.41k     5.34k   60.44k    71.39%
  1550171 requests in 10.00s, 362.20MB read
Requests/sec: 155069.87
Transfer/sec:     36.23MB

結果としては、15.5万req/sec、36.23MB/sになりました。高速ですね!ただし、wrkを走らせたマシンはCPUを使いきっている状態でしたので、もっと出るかと思います。h2oを走らせていた方は、CPU使用率が70%程度でしたので余力がありそうです。また、今回index.htmlは短めの文字列ですが、少し長くすればすぐにGbEでは足りなくなりますね。きちんとした計測では、

– より高性能な測定器
– 10GbE環境

が必要だと感じました。

ともかくも、h2oがとても高速であることがよくわかりました。h2oはHTTP/2にも対応しているとのことなので、そちらもいつか試してみたいと思います。

注意点

– 「cowardly refusing to run as root; you can use the `user` directive to set the running user」と怒られる
→ confファイルに、user: rootと書きましょう (下記に高速なconfの例を載せました)

– h2oが1コアしか使ってくれない
→ デフォルトのconfファイルでは、num-threadsが設定されておらずデフォルトの1となるようです。num-threads:8 などとしましょう (下記に高速なconfの例を載せました)

h2o.conf
user: root
http2-max-concurrent-requests-per-connection: 1024
num-threads: 8
listen: 8080
hosts:
  "127.0.0.1.xip.io:8080":
    paths:
      /:
        file.dir: examples/doc_root
↑ userをrootにしないとrootでh2oは動かせません。さらに、num-threadsは指定しないと1なので1コアで動くため、コア数分にするなどが適切かと思います。

【LAN】ローカルで好きな名前を使う【Unbound、DNS】

追記@2015-01-04

こういった用途には、DNSMasqというフリーのソフトウェアがあることを知りました。
主にLocalのDNSとDHCPサーバの役割のようです。LinuxやBSDで動くそうです。
オープンソースのwifiルーターのファームウェア、dd-wrtには標準で付属していますのでこれを使うのが最も容易かもしれません。

dnsmasq でDNSのキャッシュサービスを気軽に動かす
http://www.usupi.org/sysad/225.html
↑とても分かりやすい記事ですので挙げておきます


管理出来るローカルエリアネットワークで、好きな名前を使いたくなる時があります。たとえば、「wiki.lo」でwikiが動いているサーバーに飛んだり(lo=localです)、「gitlab.lo」でgitlabが動いているサーバーに飛んだりできれば楽ですね。

こういったことを実現するのに適した、Unboundというソフトがあります。

ローカル内のサーバを名前解決してアクセスするためにunboundを使う


↑この方のを参考にして自分でやってみました。ほとんど↑と同様です。差分は、

– IPV6を無効にした
– unboundへアクセスしてよいものを追加した
– wiki.loとgitlab.loの2つを登録した
– macでこのunboundへ聞きに行く方法を書いた
– NECルーターの設定方法を書いた

程度の僅かなものです。以下作業ログです。

想定しているサーバーはubuntuです。

# unboundをインストール
$ sudo aptitude install unbound -y

# unbound.confを編集 (このページの下に設定例があります)
$ sudo vi /etc/unbound/unbound.conf

# unbound.confが正しい設定が確認 (以下のような出力があればOK)
$ unbound-checkconf 
unbound-checkconf: no errors in /etc/unbound/unbound.conf

# unboundを起動
$ /etc/init.d/unbound start
 * Starting recursive DNS server unbound

# digで確かめてみる
$ dig wiki.lo @localhost

; <<>> DiG 9.8.1-P1 <<>> wiki.lo @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;wiki.lo.			IN	A

;; ANSWER SECTION:
wiki.lo.		3600	IN	A	192.168.1.118

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Dec 29 21:07:44 2014
;; MSG SIZE  rcvd: 41

$ dig gitlab.lo @localhost

; <<>> DiG 9.8.1-P1 <<>> gitlab.lo @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4415
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;gitlab.lo.			IN	A

;; ANSWER SECTION:
gitlab.lo.		3600	IN	A	192.168.1.118

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Dec 29 21:07:51 2014
;; MSG SIZE  rcvd: 43

そして、他のマシンから↑のunboundに名前解決しに行くには、/etc/resolv.confを↑のサーバーに指定してやる必要があります。DHCPで自動設定される場合もありますので、その場合はDHCPサーバーの設定に↑のマシンのIPアドレスを書きましょう。

– Linuxでの設定例 (↑のunboundのサーバーのIPアドレスを192.168.1.2とします。↓のように編集してやればよいという意味です)

$ cat /etc/resolv.conf 
nameserver 192.168.1.2

– Macでの設定例

Macの場合、resolv.confを書き換えても有効ならないようです。digは可能でしたがcurlやブラウザなどでは名前を引いてくるのに失敗します。どうやらシステム環境設定から行うようです。

システム環境設定→ネットワーク→詳細→DNS→DNSサーバーで-ボタンを押して既存のものを消して+ボタンを押して「192.168.1.2」を追加→OK→適用をクリック

です。

– NECのルーター(DHCPサーバー)の設定

Aterm WR8700Nの設定方法です。
「基本設定」→「接続先設定」→「高度な設定を表示」→ネームサーバ→「サーバから割り当てられたアドレス」のチェックをはずす→プライマリDNSに「192.168.1.2」と追加→「設定」をクリック→「保存」をクリック

unbound.conf
server:
# The following line will configure unbound to perform cryptographic
# DNSSEC validation using the root trust anchor.
#    auto-trust-anchor-file: "/var/lib/unbound/root.key"
 
#ログのエラーレベルの設定 0~5まで指定可能。数字が大きいほど詳細なエラーを出力
verbosity: 2                                    

# ipv6を使用しない
do-ip6: no   
 
# unboundが動作するディレクトリ
directory: "/etc/unbound"
 
# 使用するインターフェース。以下ではデフォルトルートを指定
interface: 0.0.0.0
 
# unboundへのアクセスを許可するIPアドレス範囲
access-control: 127.0.0.1/32 allow              
access-control: 192.168.1.0/24 allow
access-control: 192.168.0.0/24 allow
 
username: "root"
 
# unboundのログファイルの出力先
logfile: "/var/log/unbound.log"
use-syslog: no
 
# ローカルのサーバの名前とIPアドレスの対応を登録
local-data: "wiki.lo. IN A 192.168.1.118"
local-data-ptr: "192.168.1.118 wiki.lo."

local-data: "gitlab.lo. IN A 192.168.1.118"
local-data-ptr: "192.168.1.118 gitlab.lo."

# 再帰的に問い合わせるためのローカル内の他のDNSサーバの指定。ない場合は省略。
forward-zone:
name: "."
forward-addr: 192.168.0.1