我正在尝试使用免费的 Google App Engine 作为我的下一个 Android 应用程序的 Google Cloud Messages 的后端,但是当我“完成”编写服务器时,它已经使用了几乎 100% 的免费前端实例小时数。我的问题是我是否以及如何改善这一点?
该应用程序是一个 servlet,每 15 分钟从 cron 作业调用一次,servlet 下载并解析 3 个 RSS 提要并检查自上次调用以来是否有任何更改,将日期保存到数据库(JDO 和 memcache,3 次调用)以知道上次运行是什么时候,以及自上次呼叫将信息发送到连接的手机后是否发生了任何变化,现在有 3 部手机已连接,这只是对 Google 服务器的一次呼叫。servlet 不返回任何数据。
这是代码
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException
{
boolean sendMessage = false;
String eventsFeedUrl = "http://rss.com";
String newsFeedUrl = "http://rss2.com";
String trafficFeedUrl = "http://rss3.com";
response.setContentType("text/plain");
Message.Builder messageBuilder = new Message.Builder();
String messageData = getFeedMessageData(eventsFeedUrl);
if (!messageData.equals(StringUtils.EMPTY))
{
messageBuilder.addData("event", messageData);
sendMessage = true;
}
messageData = getFeedMessageData(newsFeedUrl);
if (!messageData.equals(StringUtils.EMPTY))
{
messageBuilder.addData("news", messageData);
sendMessage = true;
}
messageData = getFeedMessageData(trafficFeedUrl);
if (!messageData.equals(StringUtils.EMPTY))
{
messageBuilder.addData("traffic", messageData);
sendMessage = true;
}
if (sendMessage)
{
sendMessage(messageBuilder.build(), response, debug);
}
}
private void sendMessage(Message message, HttpServletResponse response, boolean debug)
throws IOException
{
SendResult sendResult = GCMService.send(message, Device.list());
int deleteCount = 0;
for (MessageResult errorResult : sendResult.getErrorResults())
{
if (deleteCount < 200 && (errorResult.getErrorName().equals(Constants.ERROR_NOT_REGISTERED) || errorResult.getErrorName().equals(Constants.ERROR_INVALID_REGISTRATION)))
{
Device.delete(errorResult.getDeviceId());
deleteCount++;
}
}
}
private String getFeedMessageData(String feedUrl)
{
String messageData = StringUtils.EMPTY;
FeedHistory history = FeedHistory.getFeedHistoryItem(feedUrl);
Feed feedContent = RssParser.parse(feedUrl);
if (feedContent != null && feedContent.getFeedItems().size() > 0)
{
if (history == null)
{
history = new FeedHistory(feedUrl);
history.setLastDate(new Date(0));
history.save();
}
for (FeedItem item : feedContent.getFeedItems())
{
if (item.getDate().after(history.getLastDate()))
{
messageData += "|" + item.getCountyId();
}
}
if (!messageData.equals(StringUtils.EMPTY))
{
messageData = new SimpleDateFormat("yyyyMMddHHmmssZ").format(history.getLastDate()) + messageData;
}
history.setLastDate(feedContent.getFeedItem(0).getDate());
history.save();
}
return messageData;
}
调用 Device.list() 使用 memcache,因此在一次调用后它将被缓存,RSS 解析器是一个简单的解析器,它使用org.w3c.dom.NodeList
和javax.xml.parsers.DocumentBuilder
. 根据日志文件,我使用同一个实例好几天了,所以实例启动和占用资源没有问题。对 servlet 的正常调用在日志中如下所示,
ms=1480 cpu_ms=653 api_cpu_ms=0 cpm_usd=0.019673
我对接下来要尝试什么有了一些想法,尝试异步执行 RSS 下载调用以最小化请求时间。将 RSS 解析移至后台作业。还有什么可以做的?感觉就像我的代码在这里犯了一些基本错误,因为如果不能在 24 小时内调用 100 次 servlet 而不会消耗 100% 的前端时间,那么普通的 Web 应用程序如何工作。
/维克托