1. devneko

    Posted

    devneko
Changes in title
+Nginxで認証付きのキャッシュを実装する
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,53 @@
+#実現したいこと
+Nginxを使ってアプリケーションサーバーのレスポンスをキャッシュしたいケースは多いと思いますが、
+厄介なのが認証が必要なケースです。単純にキャッシュしてしまうと認証が回避されてしまいます。
+仕方ないので認証が必要なアクセスに関してはアプリケーションサーバにリクエストを毎回流すことにすれば
+やはりパフォーマンスは下がってしまいます。
+なんとか認証をアプリケーションサーバを介さずに実現し、高速な認証つきのキャッシュを実現できないか考えてみました。
+
+#仕組み
+例えば、リクエストヘッダーなどに認証トークンが付いており、これをMemcachedに問い合わせることで認証をチェックできるというシステムである場合、どうやらNginxの既存のモジュールだけで実現できることがわかりました。
+使うのはproxy_cacheの他に下記の2つの標準モジュールです。
+
+ - ngx_http_auth_request_module
+ - ngx_http_memcached_module
+
+ngx_http_auth_request_moduleに含まれるauth_requestというディレクティブを使うと、指定したURIのレスポンスが
+正常系(2xx)である場合だけリクエストを処理させることができます。
+ngx_http_memcached_moduleは、$memcached_key変数に指定したキーの内容をmemcached_passディレクティブで指定した
+ホストから取得するといったことができるモジュールです。キーがあればステータス200ですが存在しない場合は404となります。
+
+memcachedの内容を返すURIを用意しておき、auth_requestを使ってそれを認証URIにすれば、認証つきのキャッシュを実現できます。
+
+#設定例
+##前提となる構成と認証
+アプリケーションサーバ: 127.0.0.1:8080
+Memcachedサーバ: 127.0.0.1:11211
+認証:リクエストヘッダX-TOKENに認証用のトークンが設定される。Memcachedサーバには有効な認証トークンだけがキーとして設定されている。
+
+```text:nginx.conf
+http {
+ proxy_cache_path /var/cache/nginx/cache levels=1 keys_zone=zone:4m inactive=7d max_size=50m;
+
+ upstream backend {
+ server 127.0.0.1:8080;
+ }
+
+ server {
+ location / {
+ auth_request /auth;
+ proxy_pass http://backend;
+ proxy_cache zone;
+ proxy_cache_key $scheme$proxy_host$uri$is_args$args;
+ proxy_cache_valid 200 1d;
+ }
+ location /auth {
+ set $memcached_key "$http_x_token";
+ memcached_pass 127.0.0.1:11211;
+ }
+ }
+}
+```
+
+Memcachedの部分は実際にはDBやRedisへの問い合わせが必要だったり、単なる認証だけでなく複雑なアクセス条件チェックが必要だったり
+々なケースがあると思います。その場合、組み込みのLuaを使うか、認証やアクセス条件のチェックを高速に処理する専用のサーバを用意するというのも良い策な気がします。