人間とウェブの未来

「ウェブの歴史は人類の歴史の繰り返し」という観点から色々勉強しています。

C言語のアプリにmruby経由でtrusterdのHTTP/2サーバ機能を5分で組み込む方法

今日は僕が開発しているTrusterd HTTP/2 Webサーバの一つの特徴である、「HTTP/2機能のアプリ組込み」の方法を紹介したいと思います。

Cをちょっと書けるレベルの人でも5分でCアプリにHTTP/2機能を組み込んで、自分のHTTP/2サーバを実装できます。

mrubyをGitHubからcloneしてビルド

まずはmrubyをGitHubからダウンロードしましょう。

git clone https://github.com/mruby/mruby.git
cd mruby

そして、build_config.rbに必要なmrbgemを書きます。

・
・
  # include the default GEMs                                                     
  conf.gembox 'full-core'                                                        
  conf.gem :github => 'iij/mruby-socket'                                         
  conf.gem :github => 'iij/mruby-pack'                                           
  conf.gem :github => 'iij/mruby-io'                                             
  conf.gem :github => 'matsumoto-r/mruby-simplehttp'                             
  conf.gem :github => 'trusterd/mruby-http2'     
・
・                                

gemboxをdefaultからfull-coreに変更して、その下の5つのmrbgemを追記します。他はいじらなくてよいです。

そしてビルドしましょう。

rake

HTTP/2機能をmruby経由でCアプリに組み込む

今回は簡単のため、最もシンプルなC言語コードにしました。

  • mini_trusterd.c
#include <stdio.h>
#include "mruby.h"
#include "mruby/compile.h"

const char config[] = "                                       \
                       HTTP2::Server.new({                    \
                           :port => 8080,                     \
                           :document_root => './',            \
                           :server_name => 'mini_trusterd',   \
                           :tls => false,                     \
                           :worker => 'auto',                 \
                       }).run                                 \
";

int main(void)
{
  mrb_state *mrb = mrb_open();
  mrb_load_string(mrb, config);
  mrb_close(mrb);
  return 0;
}

mruby組み込みのHello Worldレベルですが、これだけでtrusterdのHTTP/2サーバ機能をCアプリに組み込めます。

ではこれを以下のようなMakefileを作ってビルドしましょう。

  • Makefile.mini
TARGET=mini_trusterd.c
BIN_NAME=mini-trusterd

MRUBY_ROOT=./
LIBMRUBY=$(MRUBY_ROOT)/build/host/lib/libmruby.a
MRUBY_CFLAGS=$(shell $(MRUBY_ROOT)/bin/mruby-config --cflags)
MRUBY_LDFLAGS=$(shell $(MRUBY_ROOT)/bin/mruby-config --ldflags)
MRUBY_LDFLAGS_BEFORE_LIBS=$(shell $(MRUBY_ROOT)/bin/mruby-config --ldflags-before-libs)
MRUBY_LIBS=$(shell $(MRUBY_ROOT)/bin/mruby-config --libs)

all:
          gcc $(MRUBY_CFLAGS) $(MRUBY_LDFLAGS) $(TARGET) $(LIBMRUBY) $(MRUBY_LDFLAGS_BEFORE_LIBS) $(MRUBY_LIBS) -o $(BIN_NAME)

このMakefileはmrubyディレクトリの中にいる前提で書いています。このファイルをMakefile.miniという名前で保存して、以下のようにビルドします。

make -f Makefile.mini

すると、mini-trusterdというバイナリが生成されると思います。これを以下のように実行しましょう。

./mini-trusterd

カレントディレクトリに適当にindex.htmlを作成しておきます。

そして、nghttp2のアプリケーションであるh2loadでこのHTTP/2サーバにアクセス+ベンチマークしてみます。

$ h2load -v -c 500 -m 100 -n 8000000 http://127.0.0.1:8080/index.html
starting benchmark...
spawning thread #0: 500 concurrent clients, 8000000 total requests
progress: 10% done
progress: 20% done
progress: 30% done
progress: 40% done
progress: 50% done
progress: 60% done
progress: 70% done
progress: 80% done
progress: 90% done
progress: 100% done

finished in 18.66s, 428785 req/s, 20.05MB/s
requests: 8000000 total, 8000000 started, 8000000 done, 8000000 succeeded, 0 failed, 0 errored
status codes: 8000000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 392247487 bytes total, 72232487 bytes headers, 176000000 bytes data
                     min         max         mean         sd        +/- sd
time for request:     1.03ms    274.31ms     72.14ms     35.43ms    76.55%

428,785req/secという爆速なHTTP/2サーバがこのように5分でできました。やった!

まとめ

ということで、今回はtrusterdのHTTP/2サーバ機能をC言語に組み込む方法を紹介しました。 今回は組み込んで実行するだけの最小限のコードにしていますが、Cで書かれたアプリの中にこれを書くだけでHTTP/2サーバになりますし、C言語とmruby間でデータの受け渡しを行うようにすれば、HTTP/2で外部とのデータ連携やデバイス間通信も可能になるでしょう。

そういえば、人工衛星にmrubyを載せるみたいなプロジェクトがあった気がするので、ぜひそこにこのようにmruby経由でHTTP/2機能を組み込んで、地上から人工衛星にHTTP/2通信してみたいものです。