本稿は、第2回WSA研究会で発表した内容の予稿である。末尾に当日の質疑応答を追記している。
websystemarchitecture.hatenablog.jp
Rubyを書いていると、サーバを書きたくなることがあります。皆さんもそうだと思います。
ということで今日はRubyでスッとサーバを書くためのgem、serverengineの簡単な使い方メモ。
そもそも的に、Rubyでただサーバを書くのは非常に簡単である。具体的には Kernel#loop
などを回してその中でリクエストを待ったり、何かしら処理を行えば終わり。特別なgemは必要ないし、TCPを扱うクラスなども組み込みで用意されている。
以下のような9行のスクリプトを起動すれば、サーバを書いたと言える。ところで TCPServer#accept_nonblock
でないと、acceptでブロックしてしまって終了処理が遅れたりするのでノンブロッキングの方のAPIを好んで使うのがいいだろう。
require 'socket' server = TCPServer.new(5310) loop do c = server.accept_nonblock(exception: false) if c.is_a?(IO) c.puts("Hello") c.close end end
$ telnet localhost 5310 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. Hello Connection closed by foreign host.
とはいえこの簡素なサーバをプロダクションの何かに投入するのは不安があるだろう。具体的には運用面。きょうびのサーバーは、以下のような機能を実装していてほしい。
ruby hoge.rb
だとカッコ良くないので、かっこいい名前をpsコマンドで出したい(?)これらをRubyで一から実装していくのはなかなか手間であるが、serverengine gemを使えばこれらの機能はそのままパッケージングされている。
続きを読む急にinitが何をしているのか、何をすべきなのかが気になったので調べてみた。一緒に600行強のinit実装であるtiniのソースコードをざっくり読んだ。この場を借りてメモしていく。
RubyコミュニティなどではPassengerで有名なPhusion社のブログに、Docker and the PID 1 zombie reaping problemという記事が掲載されている。
みたいな内容が書いてある。詳細は読んでみてほしい。
システムコンテナ(参考)と呼ばれる種類のコンテナを作る場合、任意のプログラムをコンテナ内部のPID=1とするのではなく、上記のような振る舞いをする軽量なinitプログラムを経由して呼び出すというプラクティスがある。tiniはそういった軽量initの一つで、dockerの --init
オプションで使われるコマンドとしても知られている。
“A tiny but valid init
for containers”と自称している。
2018/04/16現在、プログラムの主要部分である tini.c
は611行しかない。読み切るのもそんなに難しくないので目を通してみる。単にログを出したり便利計算をするだけのマクロやdefineによる分岐はざっくり省略している。
登壇者枠です。
Infrastructure as Code/mrubyなどによるConfiguration as Codeの話をしました。
もともとこの倍の分量のスライドが発生して笹田さんにご心配をかけてしまいましたが、なんとか時間通り? 話せました...。
当スライドで後半でいった内容だったり、僕が最近やっているようなことについて、本当に純粋に「なんでやっているの?」という質問が何人かからありました。Kubernetesの「Railに乗って」コンテナをオーケストレーションしてビジネスをドリブンする、そういうのも確かにエンジニアとして生きるにあたり有力な選択肢だと思います。
でも僕にとって興味のあることは、そもそもKubernetesとか、コンテナとか、それを支えるLinux自体とかがどうなっているかというところであり、興味を持った分野に関しては 世界の本当のこと を知りたいので、そのアプローチとしてまず自分で手を動かす、ということを選んでいるにすぎません。
どんな技術であっても、その本当のところを知っている人というのはとても少なく、少ない側の人間になりたいと常々考えているのでした。
ここでRubyの話に繋がるんですが、世界の本当のことを知るための道具として10年間使い込んできたRubyという道具(あるいは「ブキ」)は、僕にとっては本当に便利です。
プログラマにとっては、何かを理解する最大の方法は、その何かを実装することだと思いますが、僕にとっては自分の考えたことと現実の実装をインピーダンスミスマッチなくつなぐことができる最大の道具は、Rubyなのであります。
エンジニアとして駆け出しの頃にRubyに出会えて、ここまで、曲がりなりにも一緒に歩め、25周年という大きな節目でお話をできたことは非常に幸運だと思います。
これからも、Rubyとそしてmruby(その結果としてのC言語...)を書いて、世界について詳しくなっていこうと思っています。
素晴らしい場を企画してくださった笹田さんをはじめ、関係する皆様ありがとうございました!
思うところがありHaconiwaの開発を再開し、一緒に大きめの変更を入れていこうかなという気持ちになった。
とりあえず、ずっとXenialを使っていたのだけど、Ubuntu 18.04 LTS (Bionic Beaver) を先んじて使って開発するようにした。もう直ぐ alpha 2 とのこと
Vagrantfileは以下のように適当に...
Vagrant.configure(2) do |config| config.vm.define :ubuntu_bionic do |ubuntu| ubuntu.vm.provider "virtualbox" do |vbox| vbox.cpus = 4 end ubuntu.vm.box = "ubuntu/bionic64" ubuntu.vm.network "private_network", ip: "192.168.98.209" end end
ifdownがない、というエラーが出ることがあるが、aptでifupdownを直接入れてvagrant reloadでよろしい。
sshできたら開発用パッケージを入れる。Haconiwaに必要なのは今の所こういう感じ。
sudo apt update sudo apt install \ build-essential util-linux rake \ psmisc bison git cgroup-bin \ libpam0g-dev autotools-dev \ autoconf libtool flex parallel
一通り入ったらチェックアウトして rake
一発でビルドできるようにはしている。いろいろとスタティックリンクするので、関連ライブラリをダウンロードしていて、そこは時間がかかる。
git clone https://github.com/haconiwa/haconiwa.git && cd haconiwa rake
テストは、mtest/bintestともにrootで実行してください(通らないものがあるかも、と思ったけどまだ通るので作業が減った)。
sudo rake test:mtest sudo rake test:bintest
バージョンなどは以下のように確認。なお、このバイナリを /usr/local/bin
などに転がしてパスを通しておけばあとはややこしいこともなく普通に使えます。
$ ./mruby/bin/haconiwa version haconiwa: v0.8.9 $ ./mruby/bin/haconiwa revisions mgem and mruby revisions: -------- MRUBY_CORE_REVISION d6e41c3e512673dac91906416a9c4543bbb2ab19 mruby-argtable 35693d4d220aa2a050a9ba95d4ac08bda9112cc0 mruby-capability 02ba73d48c448990a150462353a1cee2ec8d8ba3 mruby-cgroup 82da3507aa848c78198ab03efd68cc8a314d3c4f mruby-cgroupv2 e73faa0b126b5788bd6a4ffaa630c50550d143ff mruby-dir 14bc5c3e51eac16ebc9075b7b62132a0cf5ae724 mruby-env 57f0d737a4ece49dc5b6f1c7ee09b0bc8f8adf87 mruby-exec 6c204553d3e1e473ca85b0e10f37b7bd80f45394 mruby-forwardable f3728d96ef25bb038f113863cc30195d44a41d35 mruby-io 3c8e1f94c44252c836f79a48bb17726da28e2756 mruby-linux-namespace 353734cac319c1674becc308cec308685addcb7d mruby-localmemcache ae9e0f0816a7610a1237e86ad18db01d1459498b mruby-lockfile 37840c81bc0d404e06a9b731aa95dadc25caf45a mruby-mount 07054185c1f35ef7ec9c96aa54e6a295d51221c8 mruby-onig-regexp 170aecd88f6ee49ae9a5632735591ebd38993943 mruby-pack 383a9c79e191d524a9a2b4107cc5043ecbf6190b mruby-process 074a1e0bd93af38f33183351f171e2e4c1ec2e83 mruby-process-sys b8a16a55d4d7ff2bb08c9d2233a751aff9fd1cae mruby-procutil 71ef2b80fcb24738418b767200c3f6249323d21e mruby-resource 421fbbd5148cbcfe56ba3408165e1331791c5e05 mruby-seccomp 82d765628f62d24a774b86f8e59eb24f9258951f mruby-sha1 c33930cb783a63a115b95fbe2d0ce73c353d27c3 mruby-shellwords 2a284d99b2121615e43d6accdb0e4cde1868a0d8 mruby-signal-thread 154023c174dc2d1bc47880114feb577c8ad100a0 mruby-sleep 7a2a6a35cae42894e2ac1ef93548af83fec9b275 mruby-socket ab54185005ec87fe4f5b10df95ad29659884141b mruby-syslog 24f2b4dc0e0ed23c5524c542b89bbb4b8cb6d97d mruby-thread 52e889b3bfefcc74a223b7560143fe6591d7fa63 mruby-timer-thread 5675cd7257219bd0a6e1012b67b36b76316c01c4 mruby-uname 422f61705a1232f8d033ace3945826ea6b0421a8 $ uname -a Linux foo.jp 4.13.0-25-generic #29-Ubuntu SMP Mon Jan 8 21:14:41 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
というのを公式ドキュメントに入れたい...。そういうのもぼちぼち。