ngx_mrubyを使ってコンテンツベースのルーティングを行ってみる

Pocket

第35会 PaaS勉強会 で Amalgam8 というルーティングサービスが紹介されていて、ふとngx_mrubyを使えばこういうものを作ることはできそうだな、と思ったので試してみた。なお、今回のコードはtakaishi/ngx_mruby-content-base-routingに置いてあります。

今回は、以下の図のような構成とする。基本的にngx_mrubyはproductionサービスにアクセスを流すが、「X-Environment」に「STAGING」を指定した場合だけstagingサービスに流す。

 

curlを用いた応答は以下のようになり、ヘッダによってレスポンスが変わる。

# production サービス
$ curl http://localhost:8000
Hello World!

# staging サービス
$ curl http://localhost:8000 -H 'X-Environment:STAGING'
[staging] Hello World!

 

これを実現するnginx.confが以下。ヘッダ情報を見て、条件に合致したかどうかでupstreamのサーバーを書き換えるような仕組み。

user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log warn;
pid       /var/run/nginx.pid;

events {
    worker_connections 1024;
}

http {
  upstream dynamic {
    server 127.0.0.1:80;
  }

  upstream dynamic_production {
    server production:8000;
  }

  upstream dynamic_staging {
    server staging:8000;
  }

  server {
    listen       80;

    location / {
      mruby_rewrite_handler_code '
        Server = get_server_class
        u          = Nginx::Upstream.new "dynamic"
        production = Nginx::Upstream.new "dynamic_production"
        staging    = Nginx::Upstream.new "dynamic_staging"

        hin = Nginx::Headers_in.new

        if hin["X-Environment"] == "STAGING"
          u.server = staging.server
        else
          u.server = production.server
        end
        Nginx.return Nginx::DECLINED
      ';
      proxy_pass http://dynamic/;
    }
  }
}

現在ロードバランサとしてnginxを使っているのであれば試してみてもいいかもしれない。いきなり専用のツールを使うよりは障壁が低そうだ。もちろん、Kubernetesのようなオーケストレーションに最適化されているかというとそうではないので、場合に応じて使い分ける必要はあるだろう。また、serverの切り替えを確率ベースにすればstagingに全体の1%だけアクセスを流す、ということもできそうだ。

 

Leave a Reply

Your email address will not be published. Required fields are marked *