译 在Heroku上部署Java应用-部署Java
原文:https://devcenter.heroku.com/articles/java
本篇文章是使用Java与嵌入式服务器Jetty在Heroku上部置应用的快速入门。
本篇本章使用的样例代码在Github上:https://github.com/heroku/devcenter-java。
关于Jetty的使用,我发现了一篇很好的文章:http://blog.csdn.net/kongxx/article/details/7237034,用于帮助快速入门Jetty。
先决条件
基础的Java知识,包括安装好了任意版本的JVM与Maven3(作用如同Ant,用于编译管理源码等,在部署Java于Heroku上时基本的Maven知识很重要,推荐一本好书《Maven实战》,作者的网址:http://www.juvenxu.com/mvn-in-action/)。你的应用必须能够运行在版本为6和7的OpenJDK上(OpenJDK8只有测试版可用)。
一个Heroku用户帐号,可以免费申请:https://api.heroku.com/signup/devcenter。
本地开发环境配置
如果你使用的是Eclipse,你可以跳过此步,直接使用Eclipse的Heroku插件,详情:https://devcenter.heroku.com/articles/getting-started-with-heroku-eclipse。
个人感觉没有必要来安装Heroku插件,手动配置一下Eclipse就可以直接整合Maven,Jetty运行于Eclipse之上,关于整合Jetty与Maven在Eclipse中运行可以参考博文:http://blog.csdn.net/whuslei/article/details/6647275。
关于Heroku工具包的安装参见我的上篇博文:http://lzqwebsoft.herokuapp.com/show/20130217034925.html。
编写自己的APP
你可以使用Maven构建工具在Heroku上运行任意的Java应用。例如,我们将使用Jetty编写一个Java WEB应用,它是只有一个用于启动的main方法的基础性Servlet类。
src/main/java/HelloWorld.java:
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.*; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.*; public class HelloWorld extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().print("Hello from Java!\n"); } public static void main(String[] args) throws Exception{ Server server = new Server(Integer.valueOf(System.getenv("PORT"))); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); context.setContextPath("/"); server.setHandler(context); context.addServlet(new ServletHolder(new HelloWorld()),"/*"); server.start(); server.join(); } }
编写pom.xml声明依赖
Heroku就是通过存在的pom.xml文件来识别Java应用的。如下我们为上面的Java/Jetty应用创建了一个示例的pom.xml文件:
pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <version>1.0-SNAPSHOT</version> <artifactId>helloworld</artifactId> <dependencies> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-servlet</artifactId> <version>7.6.0.v20120127</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.4</version> <executions> <execution> <id>copy-dependencies</id> <phase>package</phase> <goals><goal>copy-dependencies</goal></goals> </execution> </executions> </plugin> </plugins> </build> </project>更多关于pom.xml文件的配置,请参考Maven的使用;pom.xml诀定着你的应用在Heroku上运行的环境。
为了阻止Maven构建的文件进入git管理的版本库中,创建如下的文件:
.gitignore:
target
正如文件的名字一样,它用来告诉工具git,由mavan生成的target文件被忽略,不被跟踪。
这里忽略target文件,是因为当你的源代码被git pushing到Heroku云端时,它会自动的被Heroku云端上的Mavan工具来构建,运行在一个临时的安全区中,因此跟踪pushing本地的target将会是多余的。
注意:这里你上传的应用运行在Heroku的临时区中(这就是后面说的Web dyno),每次运行时都会重新构建运行,因此在这建议你的java应用运行过程中不要有保存文件的操作,因为这些文件的都将会是临时的,如果需保存数据,建议还是保存到Heroku提供的数据库中(这个算是我部署Java应用于Heroku上时总结的一点经验吧)。
在本地构建和运行你的应用
构建你的应用于本地,使用如下命令:
$ mvn package
当构建时,Maven会收集本应用的依赖的jar架包于目录target/dependency中。因此在运行此应用时,需要先设置一个PORT的环境变量,并将此应用依赖的Java架包放入classpath中,运行上面的应用于本地,使用如下命令:
在Mac & Linux上:
$ export PORT=5000 $ java -cp target/classes:"target/dependency/*" HelloWorld(双引号用于阻止*号在Shell中被解释为通配符)
在Windows上:
$ set PORT=5000 $ java -cp target\classes;"target\dependency\*" HelloWorld这时你将会看到类似的如下信息:
2012-01-31 15:51:21.811:INFO:oejs.Server:jetty-7.6.0.v20120127 2012-01-31 15:51:21.931:INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null} 2012-01-31 15:51:21.971:INFO:oejs.AbstractConnector:Started [email protected]:5000这时打开浏览器,在其中输入:http://localhost:5000来运行本应用。
声明处理类型文件Procfile
在你应用的根目录下,使用一个Procfile文本文件来声明,将在启动的web dyno中使用什么的命令来执行你的应用。本应用中,我们只需要简单的运行Helloworld class文件:
如下Procfile
文件:
web: java -cp target/classes:target/dependency/* HelloWorld(注意:双引号在Procfile文件是需要的)
选择一个JDK版本(可选)
默认情况下,你的应用在Heroku上将会使用OpenJDK 1.6。然而你可以在system.properties
文件中通过使用java.runtime.version=1.7
命令来强制声明,使用指定版本的JDK,如下system.properties
文件:
java.runtime.version=1.7你还可以指定1.6,1.7或1.8(测试版本)版本。
使用Git管理跟踪你的APP变更
现在在你的App中有三个主要的组件:构建配置文件pom.xml,Heroku的处理类型文件Procfile
,和我们的应用原码文件src/main/java/HelloWorld.java
,现在就可以使用Git跟踪管理它,使用如下命令:
$ git init $ git add . $ git commit -m "init"第一条git命令是创建一个新的git库。第二条是指定将此应用的所有文件跟踪入库。第三条是提交文件跟踪入库。
关于简单的git的简单的使用可以参见我的另一篇博客:http://blog.csdn.net/xianqiang1/article/details/6944042
部署你的应用于Heroku上
使用如下命令在Heroku云端上创建一个应用:
$ heroku create Creating stark-sword-398... done, stack is cedar http://stark-sword-398.herokuapp.com/ | [email protected]:stark-sword-398.git Git remote heroku added这里生成的应用名称是系统自动生成的,如这里的是stark-sword-398,可以通过heroku create [app名]的命令来创建一个指定名称的应用。
这里的app名称也可以后期在Heroku应用面板中的Settings菜单中重命名(注意:重命名后,如果要使用git跟踪应用,还要修改git对应的远程仓库路径)。
Pushing代码并部署你的应用于Heroku上:
$ git push heroku master Counting objects: 47, done. Delta compression using up to 4 threads. Compressing objects: 100% (25/25), done. Writing objects: 100% (47/47), 10.25 KiB, done. Total 47 (delta 19), reused 42 (delta 17) -----> Heroku receiving push -----> Java app detected -----> Installing OpenJDK 1.6... done -----> Installing Maven 3.0.3... done -----> Installing settings.xml... done -----> executing /app/tmp/repo.git/.cache/.maven/bin/mvn -B -Duser.home=/tmp/build_3k0p14ghrmdzs -Dmaven.repo.local=/app/tmp/repo.git/.cache/.m2/repository -s /app/tmp/repo.git/.cache/.m2/settings.xml -DskipTests=true clean install [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building helloworld 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ ... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 10.062s [INFO] Finished at: Tue Jan 31 23:27:20 UTC 2012 [INFO] Final Memory: 12M/490M [INFO] ------------------------------------------------------------------------ -----> Discovering process types Procfile declares types -> web -----> Compiled slug size is 948K -----> Launching... done, v3 http://empty-fire-6534.herokuapp.com deployed to Heroku这里只是简单的使用git命令pushing你的代码到heroku中,Heroku就会自动的根据
Procfile
与system.properties
文件来运行的你应用。访问你的应用
现在你已经部署了你的代码到Heroku上了,并通过Procfile文件指定了处理类型。现在你就可以要求Heroku来运行它。Heroku运行相关的命令是在一个dyno中-一个轻量级的容器,它是Heroku上的基本单位组件。
为了确保你已经有了一个dyno来运行应用,使用如下命令来指定dyno个数:
$ heroku ps:scale web=1同时你还可以使用heroku ps命令来检查你的应用现在已经拥有的dyno个数,如下:
$ heroku ps === web: `java -cp target/classes:target/dep...` web.1: up for 5s这里只有一个dyno在运行。
在Heroku中,免费提供的dyno个数只有一个。
现在我们就可以使用heroku open命令调用浏览器访问你的应用,如下:
$ heroku open Opening empty-fire-6534... done你也可以直接在浏览器中输入URL地址来访问:http://App名.herokuapp.com
Dyno的空转期与规塻数
由于每个dyno都存在一定的空闲期,因此如果只使用单个dyno,会使应用出期停怠期,即当每次dyno的空闲期过后几秒,第一次用户请求将会很慢,但后续的请求将会很正常。
为了避免这样的事发生,你可以指定多个dyno,例如:
$ heroku ps:scale web=2对于每一个应用,Heroku提供750个免费的dyno小时(750 free dyno-hours),使用2个dynos来运行你的应用如果超过这个范围,将每月支付相应的费用,所以为了免费,还是要将规模数调整为1:
$ heroku ps:scale web=1
查看日志
Heroku是按照你的应用运行在Dyno组件的时间顺序来输出处理日志的。Heroku的Logplex提供一个单一的通道来处理这些事件。
查看你的应用运行日志,可以使用heroku logs的日志命令,如下:
$ heroku logs 2012-01-31T23:27:27+00:00 heroku[web.1]: Starting process with command `java -cp target/classes:target/dependency/* HelloWorld` 2012-01-31T23:27:28+00:00 app[web.1]: 2012-01-31 23:27:28.280:INFO:oejs.Server:jetty-7.6.0.v20120127 2012-01-31T23:27:28+00:00 app[web.1]: 2012-01-31 23:27:28.334:INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null} 2012-01-31T23:27:28+00:00 app[web.1]: 2012-01-31 23:27:28.373:INFO:oejs.AbstractConnector:Started [email protected]:8236 2012-01-31T23:27:29+00:00 heroku[web.1]: State changed from starting to up
下一步:数据库驱动应用
接着将会着手翻译在Heroku上使用java访问数据库的文章,时间不确定。
暂无评论