7

Apache HTTP クライアント ライブラリを使用して、Android デバイスから Rails Web サービスを呼び出すときに、次のシナリオを克服したいと考えています。

シナリオ :

クライアント (Android) : サーバー データベース (MySQL) にいくつかのレコードを挿入するために、HTTP POST 要求 (交換形式として Apache HTTP クライアント、JSON を使用) を開始します。

(SocketTimeOutException)サーバー (Rails の Web サービス) : 要求を処理し、レコードをデータベースに正常に挿入しますが、同時にクライアント側でタイムアウトが発生します。

クライアント (Android) : タイムアウト時に、同じ HTTP POST 要求の実行を再試行し、もう一度同じレコードがデータベースに挿入され、データベースの矛盾が発生します。

誰でもこの状況を克服するのを手伝ってくれませんか。

前もって感謝します

編集:

私の現在のシナリオ:

1) ユーザーは、データを入力して送信することにより、Android アプリを使用して登録を試みます。したがって、基本的にPOSTサービスには、サーバー(RailsおよびMySql)に送信される必要なすべてのユーザーが含まれています

2) POST リクエストはサーバーによって処理され、このプロセスは基本的にデータベースにレコードを挿入し、データが挿入された USER_ID をクライアントに応答する役割を果たします。

3) ブーム!! データは MySql データベースに挿入されますが、何らかの理由でSocketTimeOutExceptionAndroid 側にあり、そのため Android 側に USER_ID がなく、ユーザーが再度登録しようとしています.... データベースの不整合と私は悲しいです:(

注 : ステップ 3) の発生は非常にまれです..しかし、サーバーがビジー状態であるか、サーバーに何らかの処理負荷がかかっている場合に頻繁に発生します..

4

3 に答える 3

1

上記の特定のケースでは、手続きにセッション Cookie を追加することをお勧めします。ユーザーがデータを投稿するときに、そのセッションの USER_ID が既に存在するかどうかを確認し、存在する場合はそれを返し、そうでない場合はデータベースの挿入を行います。したがって、最初の挿入が発生し、ユーザーが応答を受け取る前にタイムアウトが発生した場合でも、ユーザーが登録を再試行したときに応答を提供できます。DB を破棄することなく。

データベースで同一の (または一意の) レコード (ごく最近作成されたもの) を検索し、2 番目の要求でその USER_ID を返すこともできます。これは、ユーザーが送信するデータによって異なります。しかし、それが登録で、同じメールで 2 つの投稿が短時間連続して取得された場合、それは同じユーザーからのものである可能性が高くなります ...

編集前:

Rails を使用しているので、単にcreate_or_updateメソッドを利用してレコードを作成できます。基本的に、新しいレコードをやみくもに挿入するのではなく、レコードが既に存在するかどうかを確認してから更新します。

再投稿に問題がなくても、2 つのクライアントが同じ情報を同時に投稿する可能性があるため、これはおそらく対処しなければならない問題です。

これがどのように機能するかについてより詳細な説明が必要な場合は、投稿に含まれる内容についてより多くの情報を提供する必要があります。この場合、キーと一意のフィールドは、レコードが特定のユーザーにバインドされているかどうかなどの情報と同様に興味深いものです...

于 2013-02-07T12:51:35.137 に答える
0

以下のコードを使用してみてください

HttpParams httpParameters = new BasicHttpParams();
            int timeoutConnection = 30000;
            HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
            int timeoutSocket = 30000;
            HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
            HttpClient httpclient = new DefaultHttpClient(httpParameters);
            HttpPost httppost = new HttpPost(url);
            StringEntity se = new StringEntity((JSONRequest));
            httppost.setEntity(se);
            httppost.setHeader("Accept", "application/json");
            httppost.setHeader("Content-type", "application/json; charset=utf-8");
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            strResponse = httpclient.execute(httppost, responseHandler);

要件に応じてタイムアウトを設定します。

于 2013-03-04T10:54:12.143 に答える
0

#ruleは、クライアント (Android またはその他) の前に php および mysql スクリプトがタイムアウトすることを常に許可します。システムのすべてのエンドポイントでタイムアウトを適切に設定することで、これを簡単に確認できます。

具体的には、ユーザー テーブルにブール値を追加して名前を付けることができますverified

  1. ユーザーが登録するとき、verified はverified=falseデフォルトで未設定 ( ) です。
  2. ユーザーが初めてログインすると、検証済みが設定されます ( verified=true)。
  3. ユーザーが登録し、username指定されたが既に存在する場合、 verified==falseの場合は登録を許可し、それ以外の場合は登録を許可しません。
  4. ( cost ) ユーザーが登録すると、ログインする必要があります。登録ページを削除して、登録が完了し、ログインしていることを示す視覚的なインジケータをユーザーに表示することをお勧めします。私は通常、登録時に「登録中...」という進行状況ダイアログを表示してからログインに進みます。ページに表示され、「ログインしています...」という進行状況ダイアログがユーザーに表示されます。

これにより、問題が発生しなくなります。ログイン画面でエラー (タイムアウト) が発生した場合、ユーザーは再試行できるようにその画面に留まる必要があります。これは本当にAndroid(インテント)の通常の流れです。


  • もちろん、登録ページでログインを強制的にサイレントにし、機能するまで再試行を続けることができます.
  • 余分なログイン手順を削除して、最初のトランザクションでユーザーを確認することもできますが、それにはかなりの費用がかかります (リクエストごとに確認する必要があります)。
于 2013-03-04T15:45:23.013 に答える