Web服务SocketTimeOutException导致数据库不一致

时间:2013-01-30 12:07:38

标签: android web-services ruby-on-rails-3.2 http-post httpclient

我希望在Apache HTTP Client库的帮助下从Android设备调用Rails Web服务时克服以下情况

场景:

客户端(Android):启动HTTP POST请求(使用Apache HTTP Client,JSON作为交换格式)将少量记录插入服务器数据库(MySQL)。

服务器(Rails中的Web服务):处理请求并成功将记录插入数据库但同时客户端出现(SocketTimeOutException)的时间。

客户端(Android):超时时,重试执行相同的HTTP POST请求,并再次将相同的记录插入数据库并发生数据库不一致。

任何人都可以帮助我克服这种情况。

提前致谢

修改

我目前的情况:

1)用户尝试通过填写和提交数据来使用Android应用注册。所以基本上POST服务包含发送到服务器的所有必需用户(Rails和MySql)

2)POST请求由服务器处理,此过程基本上负责将记录插入数据库并使用插入数据的USER_ID向客户端提供响应。

3)BOOM !!数据被插入到MySql数据库中但由于某种原因在Android端有SocketTimeOutException,因此在Android端没有USER_ID,用户尝试再次注册........数据库不一致,我是SAD :(

注意:步骤3)的发生是非常罕见的。但是当服务器太忙或者有一些处理负载时它经常发生..

3 个答案:

答案 0 :(得分:1)

对于您在上面描述的具体情况,我建议您在会议记录中添加会话cookie。当用户发布数据时,您检查该会话是否已有USER_ID,如果是,则返回,如果不是,则执行数据库插入。因此,即使初始插入发生,然后在用户获得响应之前超时,您也可以在用户重试注册时提供响应。没有让你的数据库被破坏。

您还可以在数据库中查找相同(或其他唯一)记录(最近创建)并在第二个请求中返回该USER_ID。这将取决于用户发送的数据。但如果是注册,并且您在短时间内获得两封同一封电子邮件的帖子,那么可以肯定它来自同一个用户......

编辑前:

由于您使用的是Rails,因此您只需使用create_or_update方法创建记录即可。基本上你检查记录是否已经存在,然后更新它们而不是盲目地插入新记录。

这是一个你可能不得不处理的问题,因为即使你没有重新发布的问题,两个客户也可能同时发布相同的信息。

如果您想要更详细地说明其工作原理,您必须提供有关帖子包含内容的更多信息。在这种情况下,键和唯一字段是有趣的,因为有关记录是否绑定到特定用户等的任何信息...

答案 1 :(得分: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);

根据您的要求设置超时。

答案 2 :(得分:0)

#rule 始终允许php和mysql脚本在您的客户端(Android或任何其他)之前超时。您可以通过在系统的所有端点上适当设置超时来轻松确保这一点。

特别针对您的方案,您可以在users表中添加一个布尔值,并将其命名为 verified

  1. 当用户注册时,默认情况下已取消验证( verified=false )。
  2. 当用户首次登录时,已设置已验证( verified=true )。
  3. 如果用户注册并且指定的username已存在,则允许注册如果已验证== false 其他,则不允许注册。
  4. 费用)当用户注册时,他应该登录。最好删除注册页面并向用户显示注册已完成的可视指示器,现在我们正在登录。我通常通过在注册时显示“注册...”的进度对话框然后进入登录页面并向用户显示“登录...”的进度对话框。
  5. 这应该确保不再出现问题。如果登录屏幕上出现错误(超时),则用户应保持在该屏幕上以便他可以重试。这实际上是android(Intent)的正常流程。


    • 您当然可以强制登录在注册页面上保持沉默,并继续重试直到它正常工作。
    • 您还可以删除额外的登录步骤,只需在第一次交易时验证用户,但这将花费很多(您必须检查每个请求)