ローファイ日記

出てくるコード片、ぼくが書いたものは断りがない場合 MIT License としています http://udzura.mit-license.org/

serverengine を使い、Rubyでもサーバーを書こう

Rubyを書いていると、サーバを書きたくなることがあります。皆さんもそうだと思います。

ということで今日はRubyでスッとサーバを書くためのgem、serverengineの簡単な使い方メモ。

github.com

Rubyでサーバを書きたくなった時

そもそも的に、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.

「ちゃんとした」サーバを書く

とはいえこの簡素なサーバをプロダクションの何かに投入するのは不安があるだろう。具体的には運用面。きょうびのサーバーは、以下のような機能を実装していてほしい。

  • ログを吐いてほしい
  • pid fileを吐いてほしい
  • SIGINT、SIGTERMなどを正しく扱ってほしい。Interrupt例外とか生で出て欲しくない
  • 何ならSIGUSR2あたりを受け取ったら設定のリロードをしてほしい
  • prefork型のワーカをたくさん立ち上げて処理を負荷分散してほしい。Rubyなこともあり、マルチプロセスがいい
  • プロセスが ruby hoge.rb だとカッコ良くないので、かっこいい名前をpsコマンドで出したい(?)

これらをRubyで一から実装していくのはなかなか手間であるが、serverengine gemを使えばこれらの機能はそのままパッケージングされている。

続きを読む

initのお仕事〜tiniのコードを読んでみた

急にinitが何をしているのか、何をすべきなのかが気になったので調べてみた。一緒に600行強のinit実装であるtiniソースコードをざっくり読んだ。この場を借りてメモしていく。

the PID 1 problem

RubyコミュニティなどではPassengerで有名なPhusion社のブログに、Docker and the PID 1 zombie reaping problemという記事が掲載されている。

blog.phusion.nl

  • ゾンビプロセスをreapしてくれないと困る
  • SIGTERMなどでPID=1が先に死んだらその子プロセスを処理してくれないと困る

みたいな内容が書いてある。詳細は読んでみてほしい。

システムコンテナ(参考)と呼ばれる種類のコンテナを作る場合、任意のプログラムをコンテナ内部のPID=1とするのではなく、上記のような振る舞いをする軽量なinitプログラムを経由して呼び出すというプラクティスがある。tiniはそういった軽量initの一つで、dockerの --init オプションで使われるコマンドとしても知られている。

github.com

“A tiny but valid init for containers”と自称している。

tini のコードリーディング

2018/04/16現在、プログラムの主要部分である tini.c は611行しかない。読み切るのもそんなに難しくないので目を通してみる。単にログを出したり便利計算をするだけのマクロやdefineによる分岐はざっくり省略している。

続きを読む

Ruby25周年記念イベントでお話ししました #ruby25th

登壇者枠です。

Infrastructure as Code/mrubyなどによるConfiguration as Codeの話をしました。

speakerdeck.com

もともとこの倍の分量のスライドが発生して笹田さんにご心配をかけてしまいましたが、なんとか時間通り? 話せました...。


当スライドで後半でいった内容だったり、僕が最近やっているようなことについて、本当に純粋に「なんでやっているの?」という質問が何人かからありました。Kubernetesの「Railに乗って」コンテナをオーケストレーションしてビジネスをドリブンする、そういうのも確かにエンジニアとして生きるにあたり有力な選択肢だと思います。

でも僕にとって興味のあることは、そもそもKubernetesとか、コンテナとか、それを支えるLinux自体とかがどうなっているかというところであり、興味を持った分野に関しては 世界の本当のこと を知りたいので、そのアプローチとしてまず自分で手を動かす、ということを選んでいるにすぎません。

どんな技術であっても、その本当のところを知っている人というのはとても少なく、少ない側の人間になりたいと常々考えているのでした。

ここでRubyの話に繋がるんですが、世界の本当のことを知るための道具として10年間使い込んできたRubyという道具(あるいは「ブキ」)は、僕にとっては本当に便利です。

プログラマにとっては、何かを理解する最大の方法は、その何かを実装することだと思いますが、僕にとっては自分の考えたことと現実の実装をインピーダンスミスマッチなくつなぐことができる最大の道具は、Rubyなのであります。

エンジニアとして駆け出しの頃にRubyに出会えて、ここまで、曲がりなりにも一緒に歩め、25周年という大きな節目でお話をできたことは非常に幸運だと思います。

これからも、Rubyとそしてmruby(その結果としてのC言語...)を書いて、世界について詳しくなっていこうと思っています。


素晴らしい場を企画してくださった笹田さんをはじめ、関係する皆様ありがとうございました!

Ubuntu 18.04 LTS (Bionic Beaver)でビルドするHaconiwa

思うところがあり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

というのを公式ドキュメントに入れたい...。そういうのもぼちぼち。