行って来た!
こちらのイベントに参加して来ました!
来たかったけれどキャンセルすることになってしまった方が自分の周りにいたので、可能な限りやったことを詳細に書き起こせればと思います。
なお私自身の理解の甘さで不備があるかもですが...ご容赦ください。
座学の時間
座学の時間でudzuraさんがお話されたときの資料がこちらです!
(udzuraさんのお話はホントにずっと聞いていたいww)
ハンズオン用リポジトリと手順
※ 01-setup.md
に記載のセットアップは完了した前提
ハンズオン用のリポジトリと各種手順はこちら
負荷を取得するmrbgemを作る
mrbgemはmruby用のgemのことだと理解しました!
ローカル(Mac)
後々のために事前にgitのconfig周りの設定を確認して設定しておく
(github.user
と user.name
を設定しておく)
$ vim ~/.gitconfig $ git config --global github.user Shigeyuki-fukuda $ git config --global user.name Shigeyuki-fukuda
作業用のworkspaceに移動し、ボイラーテンプレートをジェネレートするコマンドを打ちます!
# /Users/shigeyukifukuda/handsonsで以下実行 $ cd workspace/ $ mrbgem-template mruby-loadavg Generate all files of mruby-loadavg create dir : ./mruby-loadavg create dir : ./mruby-loadavg/src ...
srcは不要っぽいので消します!
$ cd mruby-loadavg $ rm -rf src/
Vagrantに入ってビルド出来るかチェックする
$ vagrant ssh vagrant@ubuntu-bionic:~$ vagrant@ubuntu-bionic:~$ cd /vagrant/workspace/mruby-loadavg # rakeコマンドを叩く vagrant@ubuntu-bionic:/vagrant/workspace/mruby-loadavg$ rake cd mruby && rake all MRUBY_CONFIG=/vagrant/workspace/mruby-loadavg/.travis_build_config.rb Build summary: ================================================ Config Name: host Output Directory: build/host Binaries: mrbc, mrbtest Included Gems: mruby-metaprog - Meta-programming features for mruby mruby-time - standard Time class mruby-io - IO and File class mruby-pack - Array#pack and String#unpack method mruby-sprintf - standard Kernel#sprintf method mruby-print - standard print/puts/p mruby-math - standard Math module mruby-struct - standard Struct class mruby-compar-ext - Enumerable module extension mruby-enum-ext - Enumerable module extension mruby-fiber - Fiber class mruby-enumerator - Enumerator class mruby-string-ext - String class extension mruby-numeric-ext - Numeric class extension mruby-array-ext - Array class extension mruby-hash-ext - Hash class extension mruby-range-ext - Range class extension mruby-proc-ext - Proc class extension mruby-symbol-ext - Symbol class extension mruby-random - Random class mruby-object-ext - Object class extension mruby-objectspace - ObjectSpace class mruby-enum-lazy - Enumerator::Lazy class mruby-toplevel-ext - toplevel object (main) methods extension mruby-compiler - mruby compiler library mruby-bin-mirb - mirb command - Binaries: mirb mruby-error - extensional error handling mruby-bin-mruby - mruby command - Binaries: mruby mruby-bin-strip - irep dump debug section remover command - Binaries: mruby-strip mruby-kernel-ext - Kernel module extension mruby-class-ext - class/module extension mruby-loadavg mruby-bin-mrbc - mruby compiler executable mruby-test - mruby test ================================================ # ./mruby/bin/mirbでmirbのコンソールを起動 vagrant@ubuntu-bionic:/vagrant/workspace/mruby-loadavg$ ./mruby/bin/mirb mirb - Embeddable Interactive Ruby Shell > Loadavg.class => Class
今回やりたいこと
サーバーの負荷を取得するmrbgemを作ることです!
ヒントによれば、Vagrantの /proc/loadavg
の中身を見れば負荷が分かるそうなので見てみると...
vagrant@ubuntu-bionic:/vagrant/workspace/mruby-loadavg$ cat /proc/loadavg 0.00 0.03 0.00 1/365 2384
これを出力するmrbgemを作っていきます!
mrblibのコンソールを編集する
/handsons/mruby-loadavg/mrblib/mrb_loadavg.rb
を編集します!
以下のソースは最終的なudzuraさんの解答例です。
class Loadavg def self.open self.new end def initialize f = File.open("/proc/loadavg", "r") data = f.read.chomp.split f.close @avg_over_1min = data[0].to_f @avg_over_5min = data[1].to_f @avg_over_15min = data[2].to_f @runnable_tasks = data[3].split('/')[0].to_i @existing_tasks = data[3].split('/')[1].to_i @last_created_pid = data[4].to_i end attr_reader :avg_over_1min, :avg_over_5min, :avg_over_15min, :runnable_tasks, :existing_tasks, :last_created_pid end
自分の作業リポジトリにプッシュしておく
これは事前にやっておくと良さげ...
$ cd workspace/mruby-loadavg $ git init . $ git add . ; git status $ git commit $ git remote add origin git@github.com:Shigeyuki-fukuda/mruby-loadavg.git $ git push origin master
上記のように実装が完了したら、ビルドして動作確認してみます!
~/h/w/mruby-loadavg (master|✔) $ vagrant ssh # ビルド実行ディレクトリへ移動 vagrant@ubuntu-bionic:~$ cd /vagrant/workspace/mruby-loadavg # ビルド vagrant@ubuntu-bionic:/vagrant/workspace/mruby-loadavg$ rake # コンソールで負荷を取得 vagrant@ubuntu-bionic:/vagrant/workspace/mruby-loadavg$ ./mruby/bin/mirb mirb - Embeddable Interactive Ruby Shell > Loadavg.open => #<Loadavg:0x562edb9f5060 @avg_over_1min=0.22, @avg_over_5min=0.07000000000000001, @avg_over_15min=0.02, @runnable_tasks=1, @existing_tasks=366, @last_created_pid=2491>
この後の発展編
こちらは手が及ばず...(割愛)
ngx_mruby を触る
vagrant@ubuntu-bionic:~$ cd ~ vagrant@ubuntu-bionic:~$ git clone https://github.com/matsumotory/ngx_mruby.git vagrant@ubuntu-bionic:~$ cd ngx_mruby vagrant@ubuntu-bionic:~/ngx_mruby$ vim build_config.rb
以下の指示に沿って build_config.rb
を修正します。
## L32 松本さんのmruby-uname を使わないならコメントアウト # conf.gem :github => 'matsumotory/mruby-uname' ... ## L59 以降 end までの間に、今回使うmgemを指定する conf.gem github: "${github id}/mruby-loadavg" conf.gem github: "${github id}/mruby-uname" end
修正後がこちらです!
MRuby::Build.new('host') do |conf| toolchain :gcc conf.gembox 'full-core' conf.cc do |cc| cc.flags << ENV['NGX_MRUBY_CFLAGS'] if ENV['NGX_MRUBY_CFLAGS'] end conf.linker do |linker| linker.flags << ENV['NGX_MRUBY_LDFLAGS'] if ENV['NGX_MRUBY_LDFLAGS'] # when using openssl from brew if RUBY_PLATFORM =~ /darwin/i linker.flags << '-L/usr/local/opt/openssl/lib -lcrypto' end end # # Recommended for ngx_mruby # conf.gem :github => 'iij/mruby-env' conf.gem :github => 'iij/mruby-dir' conf.gem :github => 'iij/mruby-digest' conf.gem :github => 'iij/mruby-process' conf.gem :github => 'mattn/mruby-json' conf.gem :github => 'mattn/mruby-onig-regexp' conf.gem :github => 'matsumotory/mruby-redis' conf.gem :github => 'matsumotory/mruby-vedis' conf.gem :github => 'matsumotory/mruby-userdata' # conf.gem :github => 'matsumotory/mruby-uname' conf.gem :github => 'matsumotory/mruby-mutex' conf.gem :github => 'matsumotory/mruby-localmemcache' conf.gem :mgem => 'mruby-secure-random' # ngx_mruby extended class conf.gem './mrbgems/ngx_mruby_mrblib' conf.gem './mrbgems/rack-based-api' conf.gem './mrbgems/auto-ssl' # use memcached # conf.gem :github => 'matsumotory/mruby-memcached' # build error on travis ci 2014/12/01, commented out mruby-file-stat # conf.gem :github => 'ksss/mruby-file-stat' # use markdown on ngx_mruby # conf.gem :github => 'matsumotory/mruby-discount' # use mysql on ngx_mruby #conf.gem :github => 'mattn/mruby-mysql' # have GeoIPCity.dat # conf.gem :github => 'matsumotory/mruby-geoip' # Linux only for ngx_mruby # conf.gem :github => 'matsumotory/mruby-capability' # conf.gem :github => 'matsumotory/mruby-cgroup' conf.gem '/vagrant/mruby-loadavg' conf.gem '/vagrant/mruby-myuname' end MRuby::Build.new('test') do |conf| # load specific toolchain settings # Gets set by the VS command prompts. if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] toolchain :visualcpp else toolchain :gcc end enable_debug conf.gem :github => 'matsumotory/mruby-simplehttp' conf.gem :github => 'matsumotory/mruby-httprequest' conf.gem :github => 'matsumotory/mruby-uname' conf.gem :github => 'matsumotory/mruby-simpletest' conf.gem :github => 'mattn/mruby-http' conf.gem :github => 'mattn/mruby-json' conf.gem :github => 'iij/mruby-env' # include the default GEMs conf.gembox 'full-core' end
ビルドしていく
vagrant@ubuntu-bionic:~/ngx_mruby$ env NGINX_CONFIG_OPT_ENV='--prefix=/usr/local/nginx-mruby' sh ./build.sh ... ngx_mruby building ... Done build.sh ... successful vagrant@ubuntu-bionic:~/ngx_mruby$ sudo make install vagrant@ubuntu-bionic:~/ngx_mruby$ /usr/local/nginx-mruby/sbin/nginx -V nginx version: nginx/1.17.1
上手くいかない場合の救済措置
リモートの自分のリポジトリにプッシュしていない人はこちらを追加します。 自分はプッシュしたにも関わらずなぜか上手くいかなかったので、以下のgemを使用する方にしたら上手くいきました...
# conf.gem github: "Shigeyuki-fukuda/mruby-loadavg" # conf.gem github: "Shigeyuki-fukuda/mruby-uname" # 上二つの設定では何故かダメだったので下の設定をする↓ conf.gem '/vagrant/mruby-loadavg' conf.gem '/vagrant/mruby-myuname'
Hello, worldしてみる
ファイルを編集
vagrant@ubuntu-bionic:~/ngx_mruby/mruby$ sudo vi /usr/local/nginx-mruby/conf/nginx.conf
nginx.conf
... server { listen 80; server_name localhost; location / { root html; index index.html index.htm; } # この下を追加 location /mruby { mruby_content_handler_code ' Nginx.rputs "Hello #{Nginx.module_name}/#{Nginx.module_version} world!\n" '; } ....
起動と確認
vagrant@ubuntu-bionic:~/ngx_mruby/mruby$ sudo /usr/local/nginx-mruby/sbin/nginx vagrant@ubuntu-bionic:~/ngx_mruby/mruby$ curl http://localhost/mruby Hello ngx_mruby/2.1.5 world!
停止
本番では絶対にやっちゃダメなので注意...w
vagrant@ubuntu-bionic:~/ngx_mruby/mruby$ sudo killall nginx
upstreamをホスト名から動的に変更する
vagrant@ubuntu-bionic:~/ngx_mruby/mruby $ sudo docker run -ti -d -p8081:80 httpd:2.4 vagrant@ubuntu-bionic:~/ngx_mruby/mruby $ sudo docker run -ti -d -p8082:80 nginx:1.16
Nginx側の設定をいじる
nginx.conf
... server { listen 80; server_name localhost; location / { resolver 8.8.8.8; # 絶対パスで指定することに注意 mruby_set $backend /home/vagrant/ngx_mruby/mruby/step1.rb proxy_http_version 1.1; proxy_pass http://$backend; proxy_set_header Host $host; proxy_set_header Connection ""; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Real-IP $remote_addr; # root html; # index index.html index.htm; } }
mrubyを作成
/usr/local/nginx-mruby/mruby/step1.rb
data = Nginx::Var.new domain = data.http_host upstream = "" case domain when /apache/ upstream = "127.0.0.1:8081" when /nginx/ upstream = "127.0.0.1:8082" else end upstream
ローカルでcurl叩くと...
# サブドメがapacheだと ~/h/workspace (master|✔) $ curl http://apache.127.0.0.1.xip.io:8090/ <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> # サブドメがnginxだと ~/h/workspace (master|✔) $ curl http://nginx.127.0.0.1.xip.io:8090/ <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> # 存在しないサブドメインを叩くと ~/h/workspace (master|✔) $ curl http://udzura.127.0.0.1.xip.io:8090/ <!DOCTYPE html> <html> <head> <title>Error</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>An error occurred.</h1> <p>Sorry, the page you are looking for is currently unavailable.<br/> Please try again later.</p> <p>If you are the system administrator of this resource then you should check the error log for details.</p> <p><em>Faithfully yours, nginx.</em></p> </body> </html>
現在のシステムの負荷状態を出す(今日やりたかったこと)
nginx.conf
... server { listen 80; server_name localhost; location / { root html; index index.html index.htm; } location /status.json { # step2.rbのパス指定は絶対パスで行うこと mruby_content_handler /home/vagrant/ngx_mruby/mruby/step2.rb; add_header Content-Type application/json; } }
/usr/local/nginx-mruby/mruby/step2.rb
lav = Loadavg.new uname = Uname.new Nginx.rputs({ "1min" => lav.avg_over_1min, "5min" => lav.avg_over_5min, "15min" => lav.avg_over_15min, "linux_nodename" => uname.nodename, "linux_release" => uname.release }.to_json)
実行してみる
vagrant@ubuntu-bionic:~/ngx_mruby$ sudo apt install jq Reading package lists... Done Building dependency tree Reading state information... Done jq is already the newest version (1.5+dfsg-2). 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. # サーバー負荷の取得に成功! vagrant@ubuntu-bionic:~/ngx_mruby$ curl -s localhost/status.json | jq . { "1min": 0, "5min": 0.03, "15min": 0, "linux_nodename": "ubuntu-bionic", "linux_release": "4.15.0-54-generic" }
この後の発展編まで終えることが出来なかったのでそちらは割愛します(Cが出来るようになりたい...)
まとめ
総じてめちゃくちゃタメになるハンズオンでした!
普段nginxを仕事でいじることがないのものの、今回を機にシステムプログラミングにもチャレンジしていきたいと思いました!!!
udzuraさん!本当に貴重な機会をくださり有難うございました。