Skip to content

Per-username Session Quota ​

このプラグインは、ユーザー名ごとのセッションクォータを強制します。

  • セッションカウンターはユーザー名ごとに管理され、クラスター全体で同期されます。
  • 設定されたクォータに達した場合、認証は quota_exceeded で拒否されます。
  • 既存の clientid での再接続は追加のクォータを消費しません。
  • ユーザー名ごとのクォータオーバーライドにより、カスタム制限、無制限セッション、または接続ブロックが可能です。

注意

client_attrs_init 設定の client_attrs.tns を設定してユーザー名をネームスペースとして使用できる場合は、ネームスペースベースの制限を通じてこの種のセッション制限を強制できます。 ネームスペース割り当てが異なるスキームに従う場合にのみ、このプラグインを使用してください。

設定 ​

フィールドデフォルトバリデーション説明
max_sessions_per_username100正の整数(>= 1)でなければなりません。1未満または非数値は拒否されます。ユーザー名ごとのデフォルト最大同時セッション数。個別のユーザー名はオーバーライドAPIでこの値を上書き可能です。
snapshot_min_age_ms300000120000 から 900000 の範囲内でなければなりません。範囲外の値はクランプされます。スナップショットの最小経過時間(ミリ秒)。これを超えると再構築がトリガーされます。大規模クラスターでの頻繁な再構築を防ぎます。
snapshot_request_timeout_ms5000正の整数に変換可能な文字列も受け入れます。リストAPIのスナップショット要求処理のタイムアウト時間(ミリ秒)。

プラグイン設定は標準のプラグイン設定APIで更新します:

PUT /api/v5/plugins/<name-vsn>/config

ランタイムAPI ​

プラグインはプラグインAPIゲートウェイを通じてランタイムAPIを公開します。

ベースパス:/api/v5/plugin_api/emqx_username_quota

EMQX 6.3.2以降、これらのエンドポイントを呼び出すダッシュボードユーザーまたはAPIキーは plugin_api または system スコープを持っている必要があります。呼び出し元のロールとネームスペース権限も要求されたHTTPメソッドを許可している必要があります。呼び出し元が管理者相当の system スコープを必要としない限り、制限付きの plugin_api スコープを使用してください。

セッションクエリ ​

  • GET /quota/usernames: アクティブなセッションを持つすべてのユーザー名を一覧表示します。
  • GET /quota/usernames/:username: 単一ユーザー名の詳細を取得します。
  • GET /metrics: プラグインのメトリクスをPrometheusテキスト形式でエクスポートします。
  • POST /kick/:username: 指定したユーザー名のすべてのセッションをキックします。

スナップショット管理 ​

  • DELETE /quota/snapshot: スナップショットの再構築を強制します。

クォータオーバーライド ​

  • POST /quota/overrides: ユーザー名ごとのクォータオーバーライドを設定します。
  • DELETE /quota/overrides: ユーザー名ごとのクォータオーバーライドを削除します。
  • GET /quota/overrides: すべてのクォータオーバーライドを一覧表示します。

GET /quota/usernames ​

このエンドポイントは、毎回ライブのセッションデータをスキャンする代わりに、事前に構築されたスナップショットから結果を返します。

スナップショットは、ユーザー名ごとのセッション数の時点コピーであり、効率的なカーソルベースのページネーションのためにセッション数でソートされています。スナップショットはバックグラウンドで非同期に構築されキャッシュされます。現在のスナップショットが snapshot_min_age_ms より古い場合のみ新しい構築がトリガーされます。

最初のリクエストが到着しスナップショットがまだ存在しない場合、サーバーは進行中の構築が完了するまで待機します。待機時間はリクエストのタイムアウトから1秒引いた時間までです。構築が間に合えば通常の 200 レスポンスを返します。間に合わなければ 503 と部分的なデータを返します。

クエリパラメータ:

  • limit: 正の整数、最大100(デフォルト100)
  • used_gte: カーソルがない場合は必須。これは最低セッション数のフィルターです。指定された数以上のセッションを持つユーザー名のみ含まれます。正の整数 >= 1 でなければなりません。
  • cursor: 以前のリスト呼び出しで返された不透明なカーソル。省略すると最初のページが返されます。

パラメータルール:

  • used_gte のみ(カーソルなし):OK(最初のページ)
  • cursor のみ(used_gteなし):OK(used_gteはカーソルに含まれる)
  • 両方指定:400 BAD_REQUEST。フィルターはカーソルに固定されているため。
  • 両方なし:400 BAD_REQUEST

動作:

  • 結果は常にセッション数、次にユーザー名でソートされます。
  • ページネーションはカーソルベースです。最初のページは cursor を省略します。
  • 各アイテムに username、リアルタイムの used、および limit(有効なクォータ)が含まれます。
  • リアルタイムの used がスナップショットのカウントと異なる場合、snapshot_used が含まれ、キャッシュされたカウントと現在のカウントの両方を確認できます。

成功時のレスポンス構造:

  • data: ユーザー名クォータのエントリー
  • meta.limit: ページサイズ(ページネーション制限)
  • meta.count: このページのエントリー数
  • meta.total: スナップショット内の総エントリー数
  • meta.next_cursor: 次ページ用カーソル(利用可能な場合)
  • meta.snapshot: スナップショットのメタデータ:
    • node
    • generation(増分スナップショットID)
    • taken_at_ms(スナップショットのタイムスタンプ、ミリ秒)

エラー応答:

  • 400 BAD_REQUEST: used_gte がない、または used_gte とカーソルが同時に指定されている場合
  • 400 INVALID_CURSOR: カーソルが利用不可のノードを参照しているか、不正な形式
  • 503 SERVICE_UNAVAILABLE: スナップショットが再構築中
    • ボディに snapshot_build_in_progress: true、data、meta が含まれます
    • data: 進行中のスナップショットから読み取った部分的な最初のページ(構築開始直後の場合は空の場合あり)
    • meta.count: 部分的なエントリー数、meta.partial: true
    • 制限付きバックオフで同じリクエストを再試行してください

DELETE /quota/snapshot ​

即時にスナップショットの再構築を強制します。再構築開始後に {"status": "ok"} を返し、再構築はバックグラウンドで行われます。

GET /quota/usernames/:username ​

単一ユーザー名の詳細を返します。レスポンスフィールドは username、used、limit、clientids です。

アクティブなセッションがないユーザー名の場合は 404 NOT_FOUND を返します。

GET /metrics ​

プラグインのPrometheusテキスト形式のメトリクスを返します。 レプリカントノードでは、リクエストはスナップショット所有コアノードに転送されます。

現在エクスポートされているメトリクス:

  • emqx_username_count: アクティブスナップショット内のユーザー名の総数

POST /kick/:username ​

指定したユーザー名のすべてのセッションをキックします。キックしたセッション数を {"kicked": N} の形式で返します。

アクティブなセッションがないユーザー名の場合は 404 NOT_FOUND を返します。

POST /quota/overrides ​

ユーザー名ごとのクォータオーバーライドを設定します。ボディはJSON配列です:

json
[
  {"username": "user1", "quota": 1000},
  {"username": "vip", "quota": "nolimit"},
  {"username": "blocked", "quota": 0}
]

オーバーライドの意味:

quota の値意味
正の整数このユーザー名のカスタムセッション制限
"nolimit"無制限セッション(クォータ制限なし)
0ブロック:新規接続をすべて拒否

オーバーライドはディスクに永続化され、クラスター全体でレプリケートされます。ユーザー名にオーバーライドがない場合は、グローバル設定の max_sessions_per_username が使用されます。

DELETE /quota/overrides ​

ユーザー名でオーバーライドを削除します。ボディはユーザー名文字列のJSON配列です:

json
["user1", "blocked"]

GET /quota/overrides ​

すべてのオーバーライドを一覧表示します。{"data": [{"username": "...", "quota": ...}, ...]} の形式で返します。

スナップショットベースの一覧表示の仕組み ​

このセクションでは、GET /quota/usernames や GET /metrics のようなリスト形式APIのためにプラグインがスナップショットをどのように構築し提供しているかを説明します。

スナップショット所有者のルーティング ​

スナップショットはコアノード上で構築されます。GET /quota/usernames と GET /metrics は、ソートされた稼働中のコアノードリストの最初のノードとして選択されたスナップショット所有コアノードにルーティングされます。

ブルー/グリーンスナップショット ​

2つのスナップショットバッファ(ブルーとグリーン)を維持します。1つが読み取りリクエストに応答している間に、もう1つで次のスナップショットを構築します。構築が完了すると役割を入れ替えます。これにより、再構築中も古いスナップショットが利用可能なため、データギャップが発生しません。

バックグラウンドスナップショット構築 ​

スナップショットの再構築は、サーバーをブロックしないようにイールドベースのスロットリングを用いたバックグラウンドプロセスで実行されます。構築中もリストAPIは応答可能です。

運用上の考慮事項と制限 ​

このセクションでは、本プラグインを本番環境で運用する際に考慮すべきランタイムの挙動や制限について説明します。

接続バースト時のクォータ超過 ​

クォータ判定は認証時に行われますが、セッションカウンターの確定はセッションライフサイクルフックで行われます。高い同時接続バースト(特にクラスター環境)では、短時間の同期ウィンドウが発生し、あるユーザー名の同時セッション数が一時的に max_sessions_per_username を超えることがあります。

実務上の意味:

  • 本プラグインはクラスター全体でのクォータ強制を最終的整合性で提供します。
  • 極端な接続集中時には、瞬間的な厳密なクォータ強制は保証しません。

プラグイン起動時のブートストラップ動作 ​

プラグインが稼働中のクラスターにインストールされた場合、既存のクライアントセッションはフック登録前に確立されています。起動時にプラグインはローカルチャネルを走査して各セッションを登録し、クォータ状態をブートストラップします。

コアノードへのDB書き込み負荷を避けるため(特にレプリカントノードに多数の接続がある場合)、ブートストラップループはスロットリングされます:

  • セッションは100件ずつバッチ登録されます。
  • 各バッチ後、最後に書き込まれたレコードがローカルテーブルにレプリケートされるのを待ちます。ポーリング間隔は10msです。
  • 10秒以内にレプリケーションが完了しない場合、エラーがログに記録され、error レベルのログとともにブートストラップは中止されます。 タイムアウト前に登録されたセッションは保持され、残りは再接続時のフック登録で自然に拾われます。

リストAPIの 503 応答の取り扱い ​

サーバーがビジー状態またはスナップショット構築中の場合、リストAPIは 503 を返します。

503 のレスポンスボディには、進行中のスナップショットテーブルから読み取った部分的な最初のページの data 配列が含まれます。これにより、呼び出し元は空のレスポンスではなく即時にベストエフォートのデータを受け取れます。meta.partial: true フラグはデータが不完全であることを示します。構築開始直後の場合は部分ページが空の場合もあります。

APIクライアントへのガイダンス:

  • data を確認し、利用可能な部分的結果を取得してください。
  • 制限付きバックオフで再試行してください。

ダウンロード ​

各EMQXリリースのタールボール:

EMQXバージョンプラグインバージョンパッケージ
6.3.01.2.3emqx_username_quota-1.2.3.tar.gz (sha256)
6.3.11.2.3emqx_username_quota-1.2.3.tar.gz (sha256)