在本系列的第 1 部分 和第 2 部分 中,我们介绍了将 Web 应用程序迁移到 Bluemix™ 的典型 Java EE 用例。现在我们会问,如果您有一个独立(stand-alone)的 Java 应用程序该怎么办?您如何让一个具有 main()
方法的 Java 应用程序在 Bluemix 中运行?
这是一个常见的场景。可能有许多原因导致您想要这么做。您的应用程序可能是一个批处理程序,它按一个时间表运行,会在停止或睡眠之前的短时间内执行某种密集的数据处理。它可能是一个在协议(比如 AMQP)上监听命令的程序。或者它可能使用一个嵌入式 HTTP 服务器(比如 Netty)而不是框架(比如 Spring 或 JEE)。
在我们完成实现此场景的过程后,我们发现了一些有关 Cloud Foundry 和 Bluemix 的架构,以及在它们之中如何管理应用程序的有趣信息。事实证明,前面的问题有一个非常简单的答案,我们将在文末介绍。但是,除非您首先跟随我们走一些弯路,否则您无法理解 为什么 这个简单的答案是真的,或者如何自行找到这样的答案。
获取代码
“ 这是一个教程系列的第 3 部分,将介绍如何在 Bluemix 中运行独立的 Java 程序。我们会分享一些浏览 Cloud Foundry 文档,使用 CF 命令行工具,以及在 Cloud Foundry 和 Bluemix 中调试的技巧。 ”
Bluemix 是所谓的 平台即服务 (PaaS) 的一个示例。使用您的平台作为服务会让开发人员的工作更轻松,因为这样可以提供简单的工具和运行时来帮助完成开发人员必须执行的最常见任务。但是请注意短语 “最常见”。大多数 PaaS 层都共享同一哲学理念:它们假设您在开发中采取一条明确、显眼的路径。如果您偏离了该路径,它们就会为您提供一些指引,但不要期望这些踪迹被标记出来,也不要期望它们是经常有人采用的路径。
这就是我们的示例应用程序面临的问题。如果查看许多 Bluemix 应用程序示例,您会看到目前在构建 Java 应用程序时采用的最常见路径针对的是使用 Liberty Application Server 的应用程序。但我们的情况更简单。我们不需要应用服务器。我们仅有一个包含一个 main()
方法的程序。要确定如何开始,我们需要执行第一步。
为了了解程序运行情况,哪里可能出错和如何调试,我们将从我们运行的 Java 应用程序的一个简化版本开始。我们将使用 Eclipse 开发我们的代码,但不会使用针对 Bluemix 的 Eclipse 插件来部署此示例。相反,我们使用 Cloud Foundry 命令行接口,使用日志来调试。
此示例使用两个 Java JAR 文件:hellojavamain.jar 和 hellojavamainrunnable.jar。可单击上面的 “获取代码” 链接获取这两个文件。另外,如果喜欢自行构建(并学习更多知识),可执行这些步骤。
JavaSE-1.6
并单击 Finish 。 HelloJavaMain
(对于本例,在默认包中创建它就行了)。 public class HelloJavaMain { public static void main(String[] args) { for (int i=0; i<1000; i++) { System.out.println("It worked! Hello World!"); try { Thread.sleep(1000); } catch (InterruptedException e) { // This should not happen e.printStackTrace(); } } } }这只是长期运行的 Java 进程的一个简单示例。它最终将在 1000 秒后结束,这对我们的示例而言已足够长。此代码只是一个复杂示例的简化版本,而复杂示例可执行一些有趣的操作,比如处理一些数据,或者甚至监听某个异步协议上的连接。
It worked!Hello World!
现在我们将进入这种简单而幼稚的方法的有趣部分。您会认为可以像其他数十个使用 Bluemix 和 Cloud Foundry 的示例一样,只需使用 cf push
和一些额外的参数。
cf push hellojavamain-ABC -p hellojavamain.jar
。
在本例中,要推送的第一个参数是要创建或更新的应用程序的名称。 –p
参数指定您想要运行的代码的位置(即您的 JAR 文件)。
cf push hellojavamain-<your_initials> -p hellojavamain.jar
cf push hellojavamain-ABC -p hellojavamain.jar
cf push
命令的输出中看到一系列重复的消息: 0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
FAILED
cf logs hellojavamain-ABC -–recent
2015-08-09T17:09:15.31-0400 [App/0] ERR [ERROR ] CWWKZ0124E:Application myapp does not contain any modules.
main()
方法的 Java SE JAR 文件。这是我们的第一个教训:最简单、最幼稚的部署机制行不通。 这一次,您可能认为(像我当初一样),问题在于在我们完全不需要 Liberty 应用服务器时,Bluemix 默认选择了 Java Liberty buildpack。如果阅读了本系列的第 1 部分,您会知道在 Bluemix 中,还有另一个 Java 开发选项:标准的 Java buildpack 。可为 push
使用 – b
命令行选项,选择一个与自动选择的 buildpack 不同的 buildpack。
cf push hellojavamain-ABC -p hellojavamain.jar -b java_buildpack
ABC
替换为您的姓名首字母或任意 3 个随机字母。 push
,但最终得到一个错误: FAILED
Server error, status code:400, error code:170004, message:App staging failed in the buildpack compile phase
cf logs hellojavamain-ABC --recent
2015-08-09T17:25:19.52-0400 [STG] ERR No container can run this application
main()
方法执行。” main()
方法的 Java 应用程序,只要它们打包为自执行 JAR,就可以运行。” 最后一行就是我们需要的线索。在 Java 编程中,您通过在 manifest.mf 文件中规定哪个类包含 main()
方法来使 JAR 文件可执行。在 Eclipse 中,可通过不将 JAR 文件导出为常规 JAR 文件,而导出为 Eclipse 所谓的 “可运行的” JAR 文件来实现此目的。
点击查看大图
关闭 [x]
cf push hellojavamain-ABC -p hellojavamainrunnable.jar -b java_buildpack
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 down
0 of 1 instances running, 1 down
2015-09-07T10:33:35.10-0400 [DEA] ERR Instance (index 0) failed to start accepting connections
-no-route
参数添加到 push
命令中。否则,Cloud Foundry 会认为您希望将 HTTP 流量路由到您的程序。没有该参数,该类最初会加载到 Java 代码中,并正常启动和运行。但是最终, DEA 抛出了一个超时错误。 尽管在第一次尝试时应用程序实际已启动,但因为没有在监听器端口上监听它,所以 Cloud Foundry 认为它关闭了。
我们通过最后一个命令将各部分结合起来,部署我们的 Java 工作者进程:
cf push hellojavamain-ABC -p hellojavamainrunnable.jar -no-route
此刻您可能会问,指定 Java buildpack 的 –b
选项发生了什么?我们希望向您介绍 Java buildpack,您可查阅 Cloud Foundry 网站上的文档,了解为什么需要可运行的 JAR 文件和 -no-route
选项。实际上,尽管您可指定 Java buildpack,但您也可在默认的 Liberty buildpack(它构建于 Java buildpack 之上)上完成所有这些工作。您可使用任意一个 buildpack,可使用 -b
参数在它们之间切换:
cf push hellojavamain-ABC -p hellojavamainrunnable.jar -b java_buildpack -no-route
cf push hellojavamain-ABC -p hellojavamainrunnable.jar -b liberty-for-java -no-route
started
(没有关联的 URL)和一个 running
状态。 cf stop hellojavamain-ABC
cf delete hellojavamain-ABC
并回答 Y 。 我们在开发的道路上难免会走一些弯路,但最终我们找到了到达目的地的道路,学到了许多有关在 Bluemix 中调试 Java 应用程序的经验。现在您已看到如何开始将标准的独立 Java 应用程序迁移到 Bluemix。您可采取我们在本系列之前的文章中介绍的相同方法,将您的应用程序绑定到服务,并利用 Bluemix 所提供的不同服务。在未来的教程中,我们将介绍将 Java 应用程序连接到内部部署的数据库。
BLUEMIX SERVICE USED IN THIS TUTORIAL: Liberty for Java 运行时 帮助您轻松地开发、部署和扩展 Java Web 应用程序。
相关主题: Cloud Foundry Bluemix