想像してみてください。 02:17、夜のピークアップストリームが1つ死にかけています。キューは長くなっています。アナリティクスはトラフィックの一部に対してのみ新機能を有効にするよう求めています。マーケティングはページの速度を落とさないようにしています。ソリューションはバックエンドではありません。解決策は「エッジ」にあります。NginxとLua、さらに高速な「状態ノートブック」Redisです。ミリ秒単位でフィーチャーフラグをオンにし、リクエストをリダイレクトし、「おしゃべりな」クライアントを制限し、安全な場所にキャッシュを返します。⚡
NginxのLua — これは、サービスの入り口にあるミニブレインです。ヘッダー、Cookie、奇妙なパターンを見て、Redisと話し、リクエストがアプリケーションに到達する前に小さな、しかし重要な決定を下します。Redisは、カウンター、クォータ、フラグ、イデムポテンシーなど、競争や重いトランザクションなしで、アトミック性と速度を提供します。

🧠なぜLuaが限界にいるのか
⚡ 速度とノンブロッキングI/O: OpenResty / ngx_luaは、ロックなしでイベントモデルで動作します。
🧩 埋め込み:スクリプトは Nginx フェーズ(書き換え/アクセス/ヘッダー/本文/ログ)で動作を直接制御します。
🔒 原子性 Redis: Lua スクリプトは単一の操作として実行されます(データ競合はありません)。
重要な考え方:「入力時の小さなロジック」はバックエンドのリソースを節約し、細かい制御を可能にします。
🌐 Nginx + Luaでの予期しない使用
🎛️ Edge-feature flags:アプリケーションにアクセスする前に、セグメント(国、クライアントのバージョン)ごとに機能を有効にします。
🧭 スマートルーティング:加入者プラン/ABバリアントにトラフィックを送信し、Redisからルールを読み取ります。
🛡️ マイクロWAF: 正規ユーザーを妨害することなく、行動シグネチャに基づいて「ソフト」ブロックを実行します。
🧯 入力側の回路ブレーカー:一時的に患者のアップストリームを切断し、キャッシュ/プラグを提供します。
🧹 URL の正規化:正規化、ガベージクエリの圧縮、キャッシュの重複との戦い。
🔗 Redisとの関連性
🏷️ フラグ/ルール TTL で Redis に存在 → Nginx を再起動せずに瞬時に配布されます。
🧪 A/B:ユーザーの選択肢はRedisに保存されます→クエリ間の一貫性。
🚦 Rate limiting:トークンバケット/キーの注ぎ口
IP+endpointまたはuser_id。🔁 Request coalescing:バックに1つのリクエストを送り、残りは待機します(「群れ効果」を抑制します)。
🧩例: JWT検証と動的制限
1)トークンをaccess_by_luaで直接検証します
access_by_lua_block {
local jwt = require "resty.jwt"
local validators = require "resty.jwt-validators"
local auth = ngx.var.http_authorization or ""
local token = auth:match("Bearer%s+(.+)")
if not token then return ngx.exit(ngx.HTTP_UNAUTHORIZED) end
local ok = jwt:verify("shared-secret", token, {
validators.set_system_leeway(60),
validators.require_aud("my-api"),
})
if not ok.valid then return ngx.exit(ngx.HTTP_FORBIDDEN) end
ngx.ctx.user_id = ok.payload.sub
}2)Luaを介したRedisのトークンバケット(原子)
-- KEYS[1]=ключ ведра; ARGV: now(ms), rate(ток/сек), burst
local key = KEYS[1]
local now = tonumber(ARGV[1])
local rate = tonumber(ARGV[2])
local burst= tonumber(ARGV[3])
local data = redis.call("HMGET", key, "tokens", "ts")
local tokens = tonumber(data[1]) or burst
local ts = tonumber(data[2]) or now
local delta = math.max(0, now - ts) / 1000 * rate
tokens = math.min(burst, tokens + delta)
local allowed = tokens >= 1
if allowed then tokens = tokens - 1 end
redis.call("HMSET", key, "tokens", tokens, "ts", now)
redis.call("PEXPIRE", key, math.floor((burst/rate)*1000))
return allowed and 1 or 03)Nginx-Lua からの呼び出し
local redis = require "resty.redis"
local r = redis:new()
r:set_timeout(50)
assert(r:connect("redis", 6379))
local key = "tb:" .. (ngx.ctx.user_id or ngx.var.remote_addr) .. ":" .. ngx.var.uri
local allowed = r:eval(token_bucket_script, 1, key, ngx.now()*1000, 5, 10)
r:set_keepalive(1_000, 100) -- пул коннекшенов
if allowed == 0 then return ngx.exit(429) end💡制限のロジックは混合できます。VIPはRedisからより大きなburstを受け取ります。
🧰 Redis + Luaのその他のトリック
🔐 API のイデムポテンシー:TTLを持つ
idem:<hash>タイプのキー—繰り返しを切り捨てます。📦 ユニークなタスクの割り当て:セットから「作業中」リストに要素を原子的に移動します。
🔒 軽いカール:
SET key val NX PX ttl;分散型の場合は、Redlockを使用して慎重に(ネットワーク/時計のリスクを評価します)。🧮 割り当て/制限:ユーザー/組織ごとのカウンター、スケジュールによるリセット。

📏「端」が良い場合とそうでない場合
シナリオ | Nginx/Redis での Lua | アプリでより良い |
|---|---|---|
ルーティング、機能、制限 | ✅ 入口での即時解決 | — |
重い計算、ML、レンダリング | ❌ CPU を大量に消費するものには向いていません | ✅ バックエンド/ワーカー |
原子データ操作 | ✅ Redis Lua — 完璧 | — |
ビジネスルールと複雑な変換 | ⚠️ 可能ですが、注意が必要です | ✅コードベースの可読性 |
B コディケ 私たちはプログラミングの学習を楽しくわかりやすくします。ステップバイステップでスキルを磨くのに役立つ課題を伴う興味深いコースを用意しています。
また、アクティブな テレグラムチャンネル、ここでは素晴らしいアイデアについて話し合い、経験を共有し、課題を一緒に分析します。学習は有益であるだけでなく、楽しいものになります。
🧵 結果
Luaは「エッジ」で即座に解決策を提供します。フラグ、制限、ルーティング、コアリングなどです。
Redis スクリプトは、原子性と高いスループットを提供します。
重要なのは、重いビジネスロジックをNginxに移行しないことです。スマートフィルターとして使用してください。
次の「端」にどんなタスクを置きますか?書いてください、続きで分析します。 💬
