利用google app engine开发一个定时器应用
来源:互联网 发布:移动大数据公司有哪些 编辑:程序博客网 时间:2024/05/16 01:53
最近对Google App Engine感兴趣。GAE是免费的(当然也有升级收费的),默认可以建立10个免费的web应用(不过我的账号可以建立25个免费应用^__^),至于配置,如果只是做简单的应用足够应付了,例如做一个定时抓取数据的应用,又或者用goagent搭建梯子。虽然GAE这么好的产品无法在国内(appspot.com在国内是无法访问的),但利用免费的资源做一些简单的事情还是很有意义的,对于如定时抓取数据,针对海外用户数据分析等等就非常有用了。
今天就写一篇关于google app engine定时器的文章。做这个定时器的前提是,假设你已经搭建好了google app engine的开发环境,使用Java语言版本。
google app engine关于定时任务的开发文档说的比较清楚,定时方式设置也比较多样。但最高频率只能到1分钟。如果做一个秒级别的定时器就没法完成,例如每个10秒执行一次,那就不能用scheduled tasks。这是可以使用scheduled tasks与task queue结合。当然也有另外的方式,使用Background threads(后台线程),通过while(true)+sleep(10000)的方式实现定时,但目前不探讨这种方式。
如果说scheduled tasks是用来定时执行任务的可以很好理解。task queue就是任务列队,就不大好理解。字面的理解就是等待执行的任务,默认是1秒可以执行5个任务。但是以什么方式执行呢?
我一开始以为,如果设置60秒执行5次任务,把任务添加到Queue中去,是不是就可以每隔10秒执行一次任务呢?然而这种理解是错误的。即使这样设置,task queue还是会在一瞬间执行列队里的任务,而不是间隔执行。
web应用都是请求方式执行的,而每个task queue就是包含一个请求的路径。每个task queue都是通过执行请求的方式执行任务,每个task queue又可以指定延时时间执行。
这样通过定时任务scheduled tasks每隔1分钟执行一个任务,scheduled tasks也是通过请求执行定时任务的。定义10秒执行一次任务,就是在scheduled tasks里的代码里,添加5个task queue,而每个scheduled tasks之间设置10秒的延时,这样60秒后执行所有的task queue,然后有重新运行下一个scheduled tasks的循环。
好了,下面是实现的代码过程。
1.新建一个Timer的google app engine项目
为了简单起见,新建项目时,将Google SDKs的默认勾选的选项Use Google Web Toolkit去掉。
这样默认生成的项目里,有一个TimerServlet.java的类。我们将这个默认的路径作为定时器的入口。定时器执行任务就会里面的代码。采用的的GET的请求方式。
2.配置cron.xml
如何让定时器执行TimerServlet的任务?这需要添加一个cron.xml的配置文件。里面的可以执行的路径,也可以添加多个任务。目前只添加一个执行任务,没隔一分钟执行一次timer的请求。在WEB-INFO目录下添加cron.xml文件。
cron.xml的文件内容:
- <!--?xml version="1.0" encoding="UTF-8"?-->
- <cronentries>
- <cron>
- <url>/timer</url>
- <description>timer every 1 minutes</description>
- <schedule>every 1 minutes</schedule>
- </cron>
- </cronentries>
这样就可以实现每隔一分钟执行一次TimerServlet的内容了。
3.添加task queue
以上定时任务只是每分钟执行一次。现在让任务执行每隔一分钟的时间间隔里执行5个task queue任务,而每个task queue之间延时10秒,这样就可以实现每隔10秒的定时运行任务了。
修改TimerServlet.java的源码后
- package com.timer.main;
- import java.io.IOException;
- import javax.servlet.http.*;
- import com.google.appengine.api.taskqueue.Queue;
- import com.google.appengine.api.taskqueue.QueueFactory;
- import com.google.appengine.api.taskqueue.TaskOptions;
- import com.google.appengine.api.taskqueue.TaskOptions.Method;
- @SuppressWarnings("serial")
- public class TimerServlet extends HttpServlet {
- public void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws IOException {
- resp.setContentType("text/plain");
- resp.getWriter().println("Timer running");
- Queue queue = QueueFactory.getDefaultQueue();
- for(int i=0;i<5;i++){
- queue.add(TaskOptions.Builder.withUrl("/task").param("key","间隔:"+10*i).method(Method.GET).etaMillis(System.currentTimeMillis()+10000*i));
- }
- }
- }
以上代码就是添加了5个task queue,每个任务之间延时10秒,每个任务的请求路径是/task,每次请求的参数通过key传值,请求的方式是GET。
或许你会疑问:
(1).不是需要添加配置文件queue.xml吗?
因为是采取了默认的方式,所以不需要添加queue.xml。
(2).task是什么路径?
task就是下面要写的的TaskServlet.java类。
4.添加TaskServlet.java类
TaskServlet.java类就是task请求的路径,里面的内容才是真正要执行的的具体任务。目前这里只是实现一个打印获取timer传递过来的参数的代码的功能。
TaskServlet.java源码
- package com.timer.main;
- import java.io.IOException;
- import java.util.Date;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class TaskServlet extends HttpServlet{
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
- // TODO Auto-generated method stub
- resp.setContentType("text/plain");
- resp.getWriter().println("Task running");
- String key = req.getParameter("key");
- // resp.getWriter().println(new Date()+":key=="+key);
- System.out.println(new Date()+":key=="+key);
- }
- }
为TaskServlet添加url映射,在WEB-INFO/web.xml,添加以下内容:
- <!-- http task -->
- <servlet>
- <servlet-name>Task</servlet-name>
- <servlet-class>com.timer.main.TaskServlet</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>Task</servlet-name>
- <url-pattern>/task</url-pattern>
- </servlet-mapping>
- <!-- Permission -->
- <security-constraint>
- <web-resource-collection>
- <web-resource-name>task</web-resource-name>
- <url-pattern>/task/*</url-pattern>
- </web-resource-collection>
- <auth-constraint>
- <role-name>admin</role-name>
- </auth-constraint>
- </security-constraint>
如果定时器为了安全起见,可以设置禁止外部用户访问,添加了对task和timer的任务的资源限制请求。
定时器之类的程序一般只允许内部程序访问,所以需要设置管理员权限,目前为了测试,只对task进行设置权限。
只允许管理员访问,可以设置
- <security-constraint>
- <web-resource-collection>
- <web-resource-name>task</web-resource-name>
- <url-pattern>/task/*</url-pattern>
- </web-resource-collection>
- <auth-constraint>
- <role-name>admin</role-name>
- </auth-constraint>
- </security-constraint>
如果允许所有人访问,可以设置
- <security-constraint>
- <web-resource-collection>
- <web-resource-name>task</web-resource-name>
- <url-pattern>/task/*</url-pattern>
- </web-resource-collection>
- <auth-constraint>
- <role-name>*</role-name>
- </auth-constraint>
- </security-constraint>
好了,目前项目可以完成了。
点击项目,运行Run As ->Web Application
在浏览器输入localhost:8888/timer
每次刷新timer请求,task queue会执行5个时隔10秒的任务请求如图-1。将应用发布到Google App Engine就可以执行每隔10秒的任务了。
最后提供一份源码下载(为了方便网络传输,目前已将项目里lib的jar文件全部去除,如果要正常使用,需要添加相关的Google App Engine jar包,新建一个项目就有相应的jar)
Timer.zip
- 利用google app engine开发一个定时器应用
- Google App Engine应用开发系列之一 - 什么是App Engine
- 如何删除一个Google App Engine应用
- 使用 Grails 开发 Google App Engine 应用
- 使用 Grails 开发 Google App Engine 应用
- 用Google App Engine开发Go应用的简明教程
- Google App engine for Java开发的一个博客网站
- 利用Google App Engine架设网盘
- 个人新作品《云应用开发——Google App Engine & Google Web Toolkit入门指南》
- 搜集的一些Google App Engine应用
- 搜集的一些Google App Engine应用
- 最新Google App Engine应用申请教程
- 申请了一个Google App Engine帐号
- 配置最优Google App Engine开发环境
- Google App Engine JAVA 开发环境搭建
- Google App Engine JAVA 开发环境搭建
- Java 开发 2.0: 使用 Google App Engine
- google app engine 开发环境搭建
- css -- 有用的css
- js获取/设置input值
- sql rank() 根据销售次数,生成排名列
- 学不好Python?我们分析看看
- 数论板子
- 利用google app engine开发一个定时器应用
- java调用tensorflow模型进行图片分类识别
- ECMAScript6
- summernote附件上传及图片上传
- codeforces 864E 背包
- 关于创建趣味编程文章列表的倡议和通告
- Android6.0以上系统获取权限
- mysql-mysql跨机器数据迁移(命令方式)
- spring+springmvc的例子