Cron+TaskQueue+Backendsで定期実行
作成中のアニメ特化アンテナサイト
http://kumo2ji.appspot.com/
Cronはタスクを1時間に1回、1週間に1回など定期的間隔で実行するための仕組み。
TaskQueueは時間のかかるタスクをいくつかのQueueに分割して実行するための仕組み。
BackendsはFrontendと別に用意されたリソース。無料分がFrontendと別に用意されている。
この3つを組み合わせて無料リソースを最大限利用して、比較的時間のかかる処理を定期的に実行する。
まずはBackendインスタンスを作成する。
WEB-INF/backends.xmlを作成し、インスタンスの設定を記述する。
<backends> <backend name="b1"> <class>B1</class> <options> <dynamic>true</dynamic> </options> </backend> </backends>
次に、CronとTaskQueueのリクエストを受け取るためのServletを作成する。
ここでは、例として、アマゾンの商品情報をDatastoreに保存するstoreItemメソッドをアニメ数分行う処理を考える。
StoreAmazonItemServletはCronからはdoGetが呼ばれ、TaskQueueからはdoPostが呼ばれる。
Cronから呼ばれるdoGetでは、QueueFactory.getQueue("StoreAmazonItemServlet")でQueueを作成する。
getQueueの引数はqueue.xmlで指定するキュー名である。
queueには、パラメータとHostヘッダーを指定する。
このヘッダーがTaskQueueをBackendで実行するために必要な情報となる。
getBackendAddressの引数はbackends.xmlで指定したbackendの名前。
TaskQueueにより実行されるdoPostでは、storeItemメソッドを実行する。
この例では、doGetでアニメの数だけQueueが追加されたので、その回数分、doPostが呼ばれることになる。
public class StoreAmazonItemServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { AmazonService service = new AmazonService(); service.storeItem(req.getParameter("animeKeyword")); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { AnimeService service = new AnimeService(); Queue queue = QueueFactory.getQueue("StoreAmazonItemServlet"); for (String keyword : service.getAnimeList()) { queue.add(TaskOptions.Builder .withParam("animeKeyword", keyword) .header("Host", BackendServiceFactory.getBackendService().getBackendAddress("b1"))); } } }
このServletをweb.xmlに登録する。
queueはURLを指定しない場合、/_ah/queue/[キュー名]が使用されるので、そのように指定している。
<servlet> <servlet-name>StoreAmazonItemServlet</servlet-name> <servlet-class>com.kumo2ji.server.StoreAmazonItemServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>StoreAmazonItemServlet</servlet-name> <url-pattern>/_ah/queue/StoreAmazonItemServlet</url-pattern> </servlet-mapping>
WEB-INF/cron.xmlのurlにも/_ah/queue/StoreAmazonItemServletを指定することで、TaskQueueと同じServletを使用する。
もちろん異なるServletを用意し、それぞれに指定してもよい。
targetにbackends.xmlのbackend名を指定することで、CronをBackendで実行することができる。
<?xml version="1.0" encoding="UTF-8"?> <cronentries> <cron> <url>/_ah/queue/StoreAmazonItemServlet</url> <description>store Amazon item entry</description> <schedule>every day 00:00</schedule> <target>b1</target> </cron> </cronentries>
最後にWEB-INF/queue.xmlにTaskQueueを登録すれば、完了。
<queue-entries> <queue> <name>StoreAmazonItemServlet</name> <rate>2/m</rate> </queue> </queue-entries>
Cronはデバッグ環境では、実行されないので、本番環境にデプロイして、動作確認する。