2012-07-23 18 views
1

我試圖將免費的Google App Engine用作我的下一個Android應用程序的Google Cloud Messages的後端,但是當我「完成」編寫服務器時,它已經使用幾乎100%的免費前端實例小時。我擁有的問題是如果以及如何改善這一點?前端實例小時 - 如何減少使用量?

應用程序是一個從cron作業每15分鐘調用一次的servlet,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.NodeListjavax.xml.parsers.DocumentBuilder一個簡單的解析器。根據日誌文件,我使用同一天的實例,因此啓動和獲取資源的實例沒有問題。到servlet正常通話看起來像這樣在日誌中,

毫秒= 1480 cpu_ms = 653 api_cpu_ms = 0 cpm_usd = 0.019673

我有什麼要嘗試下一些想法,試着做RSS下載調用異步以最小化請求時間。將RSS解析移到背景作業。還有什麼可以做的?這感覺就像我在這裏用我的代碼做了一些基本的錯誤,因爲如果這個servlet在24小時內不能被100次調用而不消耗100%的前端時間,那麼一個普通的web應用程序如何工作。

/維克托

+2

您有沒有讀過我們的常見問題?https://developers.google.com/appengine/kb/billing#time_granularity_instance_pricing – 2012-07-24 02:23:42

+0

不,但感謝您的鏈接,它完美地解釋了我的問題。 – Viktor 2012-07-24 05:14:36

回答

4

你的空閒情況下流連了一小會兒關閉自己下來了。我不知道這是多久,但我猜測它在5-15分鐘的範圍內。如果事實上是15分鐘,那麼你的cron工作每隔15分鐘就會一直工作下去,所以你最終會每天使用24個實例小時。

您可以通過將您的cron作業設置爲每30分鐘運行一次,並查看它是否將您的實例小時使用量減半來測試此理論。

+0

感謝您指出顯而易見我完全錯過了。正如我在我的文章中所說的,我在一天中保持同一個實例活着,所以當然我會在沒有做任何事情的情況下獲得24個前端實例小時。 – Viktor 2012-07-24 05:12:02

+0

@Viktor這是正確的。也可能出現這樣的情況,即您可以支持更多的流量,而無需花費更多的實例時間。一旦有足夠的流量運行多個實例,請開始擔心優化。 – 2012-07-27 05:35:56