レコード監視 (recordWatch) の呼び出しが適切に定義されていないサービスポータルウィジェットが原因で発生する「デフォルトセマフォの枯渇」に関するエラーを解決するIssue ServiceNow インスタンス内のすべてのアプリケーションノードでデフォルトのセマフォプールがセマフォで頻繁に使い果たされます。レコード監視機能を使用するためのサービスポータルウィジェットの最近の展開 (または拡張) が、この記事に関連する要件です。 このシナリオでは、特定のインシデントレコードが更新されると、インシデントウィジェットに、選択したユーザーグループにこの更新が発生したことがリアルタイムで表示されます。 注意:この記事ではインシデントレコードの例について説明しますが、これはすべてのレコード監視テーブルと関連ウィジェットに該当します。 症状 顧客から見える症状 HTTP/1.1 429 (要求が多すぎる) ServicePortal 内およびプラットフォーム内の他の場所でのページ読み込みの応答時間が長い ページのバナーに「動いている」タイマーが表示される 1 時間あたり数千ものトランザクション (「transactions (all users)」で表示) が "/sp/rectangle/<some_sys_id に対して呼び出されます。 /stats.do ページに示すようなセマフォの輻輳。デフォルトのセマフォプールのセマフォコンシューマーは、/api/now/sp/rectangle/<some_sys_id> への呼び出しになります。 ServiceNow に表示される症状 ビッグデータからわかるデフォルトのセマフォが常に枯渇する:Splunk に表示される F5 ログには、影響を受けるサービスポータルウィジェットごとに、1 時間あたり数千件、1 日あたり数十万件のコールが表示されます。 Cause頻繁に呼び出される ServicePortal ウィジェットの一部 (必ずしも全体ではない) で、レコード監視クエリが正しく設定されていません。レコード監視の例では、3 つのパラメーターを示します。 最初のパラメーターはスコープ、2 番目のパラメーターはテーブル (incident など)、3 番目のパラメーターはクエリフィルター条件です。 フィルター条件が存在しない場合、テーブル内のレコードを更新すると、呼び出し元ウィジェットが強制的にリロードされます。これは、特定ウィジェットの ServicePortal ユーザーすべてに対して発生し、セマフォ枯渇の「フラッディングに類似している」と言われる症状が発生します。 詳細については、開発者ドキュメントのトピック 「レコード監視」を参照してください。Resolution特定のウィジェットの「監視済み」レコードが高度にフィルタリングされ、可能な最小の結果セットに固有であることを確認します。 ServiceNow サポートでは、F5 ロードバランサーログと他のツールと合わせて使用することによって、関連している可能性のあるウィジェットを特定できます。「クライアントコントローラー」と「サーバースクリプト」の両方のウィジェット定義で、次の例に示すように、必ずクエリ制限フィルター条件を設定します。 クライアントコントローラーの例 function(spUtil, $scope, $timeout) { /* widget controller */ var c = this; $scope.incidata = {}; $scope.incidata.changed = false; spUtil.recordWatch($scope, "incident", "priority=1^state!=7", function(name, data) 注意:上記の spUtil.recordWatch 文字列の 3 番目のパラメーターが、セマフォ枯渇を防ぐために重要なものです。 サーバースクリプトの例 (function() { /* populate the 'data' object */ /* e.g., data.table = $sp.getValue('table'); */ data.incidentCount = ''; var gr = new GlideRecord('incident'); gr.addQuery('priority', 1); gr.addQuery('state','!=', 7); gr.query(); data.incidentCount = gr.getRowCount();})(); 高度なデバッグと解決 注意:Chrome 開発ツールを使用すると、ブレークポイントを設定して、クライアントにプッシュされる監視レコード応答に進み、返されたデータとフィルター条件を検証することができます。 Chrome ツールコンソールで、疑わしいレコード監視コードを含むウィジェットを表示しているときに「すべてのファイルを検索」で「record.updated」を検索し、オブジェクトを選択してデバッガビューを表示します。 ブレークポイントを設定する 「監視対象」のテーブルについて、ウィジェットユーザーが考慮する必要のあるレコードを特定します。たとえば、(この例の) 別のチームが所有するインシデントなどです。レコードの更新によってクライアントへの呼び出しがトリガーされ、ウィジェットスコープが強制的にリロードされます。 次のデバッガの例は、ウィジェットのリロードをトリガーするインシデントレコードの更新を示しています。レコード監視フィルター条件が正しいかどうかは、ユーザーが確認するものではなく、また確認すべきものでもありません。 注意: この例のようなスクリプトによる更新は推奨されないため、意味のあるデータのあるシステムでは、次の手順を試さないでください。 次の例のような一括更新スクリプトを使用して監視対象テーブルのすべてのレコードを更新し、Chrome ツールの [ネットワーク] タブを確認して、問題をさらに確認します。これにより、使い果たされたセマフォ条件がトリガーされる可能性もありますが、spUtil.recordWatch フィルター条件が無視されている (または欠落している) ことが明らかになります。 このスクリプトは、別のブラウザ (シークレットモードの Firefox または Chrome) から管理者としてスクリプト - バックグラウンドで実行します。 ~~~example script~~~var gr = new GlideRecord('incident');gr.query();while(gr.next()){gr.work_notes = '.';gr.setForceUpdate(true);gr.setWorkflow(false);gr.update();}~~~/example~~~ 疑わしいウィジェットがあるユーザーのブラウザで、Chrome ツールを開いた状態で [ネットワーク] タブを表示し、別のブラウザセッションで、バックグラウンドスクリプトで一括更新を実行します。 フィルター条件が適切に適用されている場合、ユーザーまたはグループが関心を持っている特定のレコードへの更新のみがウィジェットのクライアント側の更新をトリガーします。この例では、数千の呼び出しによってシステムが過負荷になったためにセマフォが急速に枯渇し、パフォーマンスに深刻な影響を及ぼします。 適切なフィルター条件を追加してデバッグ手順を再度実行すると、ウィジェット更新の呼び出しが大幅に減少し、アプリケーションノードの安定性が保たれ、システムの過負荷を回避することができます。