48

私はRESTAPIでPOSTを使用してオブジェクトを作成しています。時々、サーバーはオブジェクトを作成しますが、クライアントは201 Created応答を受信する前に切断されます。クライアントは失敗したPOSTリクエストのみを確認し、後で再試行し、サーバーは複製オブジェクトを作成します...

他の人はこの問題を抱えていたに違いありませんよね?しかし、私はグーグルで回り、誰もがそれを無視しているようです。

私には2つの解決策があります:

A)代わりにPUTを使用し、クライアントで(GU)IDを作成します。

B)クライアントで作成されたすべてのオブジェクトにGUIDを追加し、サーバーにそれらのUNIQUE-nessを適用させます。

Aは既存のフレームワークとあまり一致せず、Bはハックのように感じます。現実の世界では、他の人はこれをどのように解決しますか?

編集:

Backbone.jsを使用すると、クライアントでオブジェクトを作成するときにGUIDをIDとして設定できます。保存されると、BackboneはPUTリクエストを実行します。RESTバックエンドが存在しないIDへのPUTを処理するようにすると、設定が完了します。

4

7 に答える 7

12

このために提案されている別の解決策は、POST Once Exactly(POE)です。このソリューションでは、サーバーが使い捨てのPOST URIを生成し、複数回使用すると、サーバーは405応答を返します。

欠点は、1)POEドラフトが標準化のさらなる進展なしに期限切れになることを許可されたため、2)それを実装するには、新しいPOEヘッダーを使用するためにクライアントに変更を加え、POEセマンティクスを実装するためにサーバーによる追加の作業が必要になることです。

グーグルすることで、それを使用しているいくつかのAPIを見つけることができます。

この問題を解決するために私が持っていたもう1つのアイデアは、条件付きPOSTのアイデアです。これについて説明し、ここでフィードバックを求めました。

一意のURI生成をクライアントにPUTできないため、POSTが必要な場合に、重複するリソースの作成を防ぐための最善の方法についてのコンセンサスはないようです。

于 2013-04-11T23:09:18.693 に答える
9

私は常にBを使用します-サーバー側に属する問題による重複の検出。

于 2013-03-01T13:53:48.160 に答える
7

重複の検出は厄介であり、非常に複雑になる可能性があります。おそらくネットワーク接続が復元されたために、本物の別個であるが類似した要求が同時に到着する可能性があります。また、ネットワーク接続が切断された場合、繰り返し要求が数時間または数日離れて到着する可能性があります。

他の回答者の識別子に関するすべての説明は、重複する要求に応答してエラーを発生させることを目的としていますが、これは通常、クライアントに新しいIDを取得または生成して再試行するように促すだけです。

この問題を解決するためのシンプルで堅牢なパターンは次のとおりです。サーバーアプリケーションは、安全でない要求に対するすべての応答を保存する必要があります。その後、重複する要求が見つかった場合、前の応答を繰り返して他に何もすることができません安全でないすべてのリクエストに対してこれを行うと、厄介な問題の束を解決できます。「重複」は、クライアントで生成されたGUIDまたはサーバーで生成されたシーケンス番号のいずれかのアプリケーションレベルのIDによって決定されます。この2番目のケースでは、要求/応答はIDの交換専用にする必要があります。私はこのソリューションが好きです。なぜなら、専用のステップによって、クライアントは自分たちが世話をする必要のある貴重なものを手に入れていると思うからです。独自の識別子を生成できる場合は、この行をループ内に配置する可能性が高く、すべての血まみれのリクエストに新しいIDが割り当てられます。

このスキームを使用すると、すべてのPOSTは空になり、POSTはアクション識別子の取得にのみ使用されます。すべてのPUTとDELETEは完全にべき等です。連続するリクエストは同じ(保存および再生)応答を受け取り、それ以上何も起こりません。このパターンの最も良い点は、カンフー(パンダ)の品質です。それには弱点があります。クライアントが予期しない応答を受け取ったときにいつでも要求を繰り返し、それを力に変える傾向です:-)

誰かが気にかけているなら、私はここに小さなグーグルドキュメントを持っています。

于 2016-02-17T09:45:35.133 に答える
5

2段階のアプローチを試すことができます。トークンを返すオブジェクトの作成を要求します。次に、2番目のリクエストで、トークンを使用してステータスを要求します。トークンを使用してステータスが要求されるまで、トークンは「ステージング済み」状態のままになります。

クライアントが最初のリクエストの後で切断した場合、クライアントはトークンを持たず、オブジェクトは無期限に、または別のプロセスで削除するまで「ステージング」されたままになります。

最初のリクエストが成功した場合、有効なトークンがあり、何も再作成せずに、作成されたオブジェクトを何度でも取得できます。

トークンがデータストア内のオブジェクトのIDになれない理由はありません。最初のリクエストでオブジェクトを作成できます。2番目のリクエストは、実際には「ステージングされた」フィールドを更新するだけです。

于 2013-03-01T14:05:37.023 に答える
3

サーバー発行の識別子

識別子を発行するのがサーバーである場合を扱っている場合は、オブジェクトを一時的な段階的な状態で作成します。(これは本質的にべき等ではない操作であるため、POSTを使用して実行する必要があります。)次に、クライアントは、ステージングされた状態からアクティブ/保存された状態(リソースのプロパティ、またはリソースへの適切なPOST)。

各クライアントは、ステージングされた状態のリソースのリストを何らかの方法で(おそらく他のリソースと混合して)取得できる必要があり、まだステージングされている場合は、作成したリソースを削除できる必要があります。しばらくの間非アクティブであったステージングされたリソースを定期的に削除することもできます。

1つのクライアントのステージングされたリソースを他のクライアントに公開する必要はありません。それらは、確認ステップの後でのみグローバルに存在する必要があります。

クライアントが発行した識別子

別の方法は、クライアントが識別子を発行することです。これは主に、ファイルストアのようなものをモデル化する場合に役立ちます。ファイルの名前は通常、ユーザーコードにとって重要であるためです。この場合、PUTを使用してリソースの作成を行うことができます。これは、すべてを同じように行うことができるためです。

これの欠点は、クライアントがIDを作成できることです。そのため、クライアントが使用するIDをまったく制御できません。

于 2013-03-01T15:11:06.340 に答える
2

この問題には別のバリエーションがあります。クライアントに一意のIDを生成させることは、この問題を解決するようにお客様に依頼していることを示します。公開されているAPIがあり、これらのAPIと統合されている数百のクライアントがある環境を考えてみてください。実際には、クライアントコードと彼の一意性の実装の正確さを制御することはできません。したがって、リクエストが重複しているかどうかを理解するためのインテリジェンスを持っている方がおそらく良いでしょう。ここでの簡単なアプローチの1つは、ユーザー入力からの属性に基づいてすべてのリクエストのチェックサムを計算して保存し、時間のしきい値(x分)を定義して、同じクライアントからのすべての新しいリクエストを過去のx分で受信したリクエストと比較することです。チェックサムが一致する場合、それは重複した要求である可能性があり、クライアントがこれを解決するためのチャレンジメカニズムを追加します。クライアントがx分以内に同じパラメータで2つの異なるリクエストを行っている場合、一意のリクエストIDが付いている場合でも、これが意図的なものであることを確認する価値があるかもしれません。このアプローチはすべてのユースケースに適しているとは限りませんが、2回目の呼び出しを実行することによるビジネスへの影響が大きく、顧客にコストがかかる可能性がある場合に役立つと思います。中間層が失敗した要求を再試行することになる、または顧客がダブルクリックしてクライアント層によって2つの要求を送信する、支払い処理エンジンの状況を考えてみます。これは、2回目の通話を実行することによるビジネスへの影響が大きく、顧客にコストがかかる可能性がある場合に役立つと思います。中間層が失敗した要求を再試行することになる、または顧客がダブルクリックしてクライアント層によって2つの要求を送信する、支払い処理エンジンの状況を考えてみます。これは、2回目の通話を実行することによるビジネスへの影響が大きく、顧客にコストがかかる可能性がある場合に役立つと思います。中間層が失敗した要求を再試行することになる、または顧客がダブルクリックしてクライアント層によって2つの要求を送信する、支払い処理エンジンの状況を考えてみます。

于 2018-04-19T17:51:48.470 に答える
1

設計

  • 自動(手動のブラックリストを維持する必要なし)
  • 最適化されたメモリ
  • ディスク最適化

アルゴリズム[ソリューション1]

  1. RESTはUUIDで到着します
  2. Webサーバーは、UUIDがメモリキャッシュブラックリストテーブルにあるかどうかを確認します(ある場合は、409と回答します)。
  3. サーバーはリクエストをDBに書き込みます(ETSによってフィルタリングされていない場合)
  4. DBは、書き込み前にUUIDが繰り返されているかどうかを確認します
  5. はいの場合、サーバーの409に回答し、メモリキャッシュとディスクにブラックリストを作成します
  6. 繰り返されない場合は、DBに書き込み、200と答えてください

アルゴリズム[ソリューション2]

  1. RESTはUUIDで到着します
  2. UUIDをメモリキャッシュテーブルに保存します(30日間有効期限が切れます)
  3. Webサーバーは、UUIDがメモリキャッシュブラックリストテーブルにあるかどうかを確認します[HTTP409を返す]
  4. サーバーはリクエストをDBに書き込みます[returnHTTP200]

ソリューション2では、メモリキャッシュブラックリストを作成するためのしきい値はメモリ内にのみ作成されるため、DBで重複がチェックされることはありません。「複製」の定義は、「一定期間内に発生するすべての要求」です。また、メモリキャッシュテーブルをディスクに複製するため、サーバーを起動する前にテーブルを埋めます。

ソリューション1では、書き込み前に常にディスクを1回だけチェックインするため、重複は発生しません。重複している場合、次のラウンドトリップはメモリキャッシュによって処理されます。このソリューションは、リクエストに影響力がないため、Big Queryに適していますが、最適化されていません。

リソースがすでに存在する場合のPOSTのHTTP応答コード

于 2019-03-06T15:10:43.127 に答える