【发布时间】:2013-05-29 05:42:26
【问题描述】:
在我的应用程序中,我想要一个实时聊天功能 - 多人(可能 5 人或更多)可以同时聊天。
我正在使用基于 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);
在其他一些名为 ReadMessages 的 servlet 中,我有以下代码
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 - 并且每秒调用一次 ReadMessages servlet 以获取新消息。
为了优化,javascript 将在后续请求中将它收到的最后一条消息的 id(或者可能是迄今为止它收到的最高 id)发送到 ReadMessage,以便响应仅包含它的消息没见过。
起初这一切似乎都有效,但我认为这段代码可能存在一些问题。
以下是我认为的错误:
可能无法读取某些消息,因为我依赖 ChatMessage 的密钥的 id 来过滤 JS 客户端之前已经看到的消息 - 我认为这不可靠吗?
-
某些写入可能会失败,因为可能同时有 5 或 6 个传入写入 - 我的理解是,如果每秒写入太多,这可能会导致
ConcurrentModificationException。 传递给实体的日期是应用程序服务器上 JRE 的当前日期 - 也许我应该在 SQL 中使用类似“sysdate()”的东西?我不知道这是否真的是一个问题。
我怎样才能修复代码以便:
所有聊天消息都将被写入 - 是否最好进行故障转移,以便如果请求失败,javascript 将重新尝试直到成功?
将读取所有聊天消息(无例外)
清理旧消息,只存储 1000 条左右的消息
【问题讨论】:
标签: java google-app-engine google-cloud-datastore