在我的應用程序中,我想要有一個實時聊天功能 - 多個人(可能有5個或更多)可以同時聊天。如何使用Google App Engine數據存儲(HRE)創建可靠的聊天?
我使用的是基於Java的Google App Engine - 這是我第一次嘗試使用GAE Datastore,我很習慣使用Oracle/MySQL,所以我認爲我的策略是錯誤的。
注:爲簡單起見,我省略任何驗證/安全檢查 在一些所謂的WriteMessage
的servlet我有以下代碼
Entity entity = new Entity("ChatMessage");
entity.setProperty("userName", request.getParameter("userName"));
entity.setProperty("message", request.getParameter("message"));
entity.setProperty("time", new Date());
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
datastore.put(entity);
在一些其他的servlet叫ReadMessages
我有下面的代碼
String id = request.getParameter("id");
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Query query = new Query("ChatMessage");
if (id != null) {
// Client requested only messages with id greater than this id
Filter idFilter = new FilterPredicate(Entity.KEY_RESERVED_PROPERTY,
FilterOperator.GREATER_THAN,
KeyFactory.createKey("ChatMessage", Long.parseLong(id)));
query.setFilter(idFilter);
}
PreparedQuery pq = datastore.prepare(query);
JsonArray messages = new JsonArray();
for (Entity result : pq.asIterable()) {
JsonObject jmsg = new JsonObject();
// Client will use this id on the next request to read to poll only
// "new" messages
jmsg.addProperty("id", result.getKey().getId());
jmsg.addProperty("userName", (String) result.getProperty("userName"));
jmsg.addProperty("message", (String) result.getProperty("message"));
jmsg.addProperty("time", ((Date) result.getProperty("time")).getTime());
messages.add(jmsg);
}
PrintWriter out = response.getWriter();
out.print(messages.toString());
在JavaScript客戶端代碼 - WriteMessage
servlet在用戶提交新消息時被調用 - 一個d ReadMessages
每秒調用一次servlet來獲取新消息。
爲了優化,javascript會在後續請求中發送它收到的最後一條消息的標識(或者迄今爲止收到的最高標識)到ReadMessage
,以便響應僅包含它所沒有的消息以前沒見過。
這一切似乎起初工作,但我想也許這個代碼有一些錯誤的東西。
這裏是什麼,我認爲是錯誤的:
有些消息可能無法讀取,因爲我依靠ChatMessage重點篩選出消息的ID的JS客戶端已經見過 - 我不認爲這將是可靠的權利?
有些寫入可能會失敗,因爲在同一時間可能有5個或6個傳入寫入 - 我的理解是,如果每秒寫入次數過多,則可能導致
ConcurrentModificationException
。在實體上傳遞的日期是應用程序服務器上JRE的當前日期 - 也許我應該在SQL中使用類似「sysdate()」的東西?我不知道這是否是一個問題。
如何修復代碼,以便:
所有的聊天信息會被寫入 - 這純粹是最好有一個故障轉移,因此如果請求失敗JavaScript的只是重新嘗試,直到成功?
所有的聊天信息會被讀取(無例外)
清理舊消息,因此,只有1000左右的郵件存儲
看一看:http://googcloudlabs.appspot.com/codelabexercise4.html –