在Docker中运行Java Spark(一)


背景

我刚意识到其实Java Spark (http://sparkjava.com,译者注:Java Spark是灵感来源于Ruby的Sinatra的Web开发框架,类似的还有Scalatra、SpringBoot等,与Scala的Scalatra有异曲同工之处)和Apache Spark(http://spark.apache.org, 译者注:Apache Spark是Apache的数据处理引擎)并不让人混淆。在接下来的内容我将展示这些这个。在所有我做过的web开发中,Java Spark是我遇到并并让我很享受的第一个Java Web的开发框架。

本文将展示如何在Docker容器中运行一个Java Spark的应用。这个教程被分解为多个Git分支还帮助说明相应的过程。

这个教程得益于来自GiantSwarm的Matthias。本教程避开了Java Spark教程的基本部分。如果你想从头开始学习的话,可以从这个Github仓库的add-java-spark-handler分支开始。

安装



步骤 1 - 构建Dockerfile

我们第一步涉及到启动一个将包含Java Spark服务器和应用的Docker容器。我们需要先生成一个初始的Dockerfile文件,并验证这个文件是可以构建并正确运行的。接着我们将在容器中安装Apache Mavin。

起始点
git clone git@github.com:bdparrish/docker-spark-tutorial.git


1,增加一个Dockerfile到这个项目根目录
FROM java:8
RUN apt-get update  
RUN apt-get install -y maven


2,构建这个Docker镜像
docker build -t bdparrish/docker-spark-tutorial .


3,验证这个Docker镜像是否正确
docker run -it bdparrish/docker-spark-tutorial


4,检查Maven版本
mvn -version}}
如果正确,你将看到如下类似的信息:
{{{Apache Maven 3.0.5 Maven home: /usr/share/maven 
Java version: 1.8.0_66-internal, vendor: Oracle Corporation 
Java home: /usr/lib/jvm/java-8-openjdk-amd64/jre 
Default locale: en, platform encoding: UTF-8 
OS name: "linux", version: "4.0.9-boot2docker", arch: "amd64", family: "unix"


5,为了加快这个教程的说明,你可以切换到一下新的git分支
git checkout build-dockerfile .

步骤 2 - 增加pom-xml

现在我们来构建一个Maven的工程, 并且增加Java Spark Core的依赖包。再次提醒, 我们一定要检查之前我们的Docker镜像是可用的。

起始点
git checkout build-dockerfile

1,增加一个pom.xml座位Maven指引
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>bdparrish</groupId>
<artifactId>docker-spark-tutorial</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
    <dependency>
        <groupId>com.sparkjava</groupId>
        <artifactId>spark-core</artifactId>
        <version>2.0.0</version>
    </dependency>
</dependencies>
</project> 

2,更新Dockerfile,增加如下内容:
WORKDIR /tutorial
ADD pom.xml /tutorial/pom.xml  
RUN ["mvn", "dependency:resolve"]  
RUN ["mvn", "verify"]  

3,重新构建Docker镜像
docker build -t bdparrish/docker-spark-tutorial .  

4,运行一个容器实例来测试我们新的Docker镜像
docker run -it bdparrish/docker-spark-tutorial

5,运行mvn verify来检验我们之前做的步骤
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.912s
[INFO] Finished at: Sun Oct 04 00:58:42 UTC 2015
[INFO] Final Memory: 7M/31M
[INFO] ------------------------------------------------------------------------

6,git checkout add-pom-xml来跳转到这个教程对应的git仓库对应的内容

步骤 3 - 增加Java-Spark服务器

从这个步骤开始我们来写些代码。我们需要一个main方法来开始我们的Java Spark服务器。

我们的maven工程大概是以下这个结构:
- java.tutorial
|- Server.java
|- DataController.java

起始点
git checkout add-pom-xml

1,首先我们增加junit依赖包到我们的工程中。增加以下部分到pom.xml的dependency的段落。
<dependency>  
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency> 

我是一个忠实的TDD拥戴者。我们第一步先做一个测试用例来测试我们正确生成了一个Server类。生成一个新的包到你的源文件目录(src/main/java), 并命名为tutorial, 然后同时生成相同的package到测试的源文件目录(src/test/java)

2,新增一个新的测试类ServerTest到tutorial包下,并在文件头包含以下引用包。
import org.junit.Assert;  
import org.junit.Test; 

3,增加以下代码到测试类中. 这是个简单的测试,但是可以帮助我们从一点点开始。如果你尝试运行这个测试,它将会失败。
@Test
public void canCreateServer() {  
// arrange / act
Server server = new Server();

// assert
Assert.assertNotNull(server);


4,前面的测试将会失败, 因为我们并没有这个服务器的类。现在让我们在tutorial包中来生成这个类。
package tutorial;
public class Server {
public static void main(String[] args) {
}


5,重新运行这个测试,结果应该是成功的。

6,现在更新我们之前的Dockerfile文件,增加这些新增的源代码。增加以下内容到Dockerfile中
ADD src /tutorial/src  
RUN ["mvn", "package"


7,再次构建我们的Docker镜像并运行它
docker build -t bdparrish/docker-spark-tutorial .  
       --
docker run -it bdparrish/docker-spark-tutorial 

8,检查并确保我们的源代码已经被正确拷贝到对应的目录。我们应该能看到我们自己所有的文件和对应的目录。
ls -R src

输出:
root@51049cdab012:/tutorial# ls -R src  
src:  
main  test
src/main:  
java  resources
src/main/java:  
tutorial
src/main/java/tutorial:  
Server.java
src/main/resources:
src/test:  
java  resources
src/test/java:  
tutorial
src/test/java/tutorial:  
ServerTest.java
src/test/resources: 

9,完成然后切换到下一个git分支
git checkout add-java-spark-server

步骤 4 - 增加Java-Spark-Handler

增加一个请求的handler到我们的代码中。 这个handler将处理所有到根目录级别(“/”)的web访问请求。

起始点
git checkout add-java-spark-server

1,给请求处理的handler增加一个测试类。这个测试类是我们对这个handler类的基本测试。
package tutorial;
import org.junit.Assert;  
import org.junit.Test;
public class MainControllerTest {
@Test
public void canCreatMainController() {
    // arrange / act
    MainController controller = new MainController();
    // assert
    Assert.assertNotNull(controller);
}


2,增加 MainController类。这个类将处理我们根目录的请求(“/”)
package tutorial;
import static spark.Spark.get;
public class MainController {


3,前面这个类并没有做什么。现在增加真正的请求处理到这个MainControlle类中。
增加新的依赖到pom.xml中。
<dependency>  
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.7.2</version>
<scope>test</scope>
</dependency> 

增加测试用例到MainControllerTest类中。
@Test
public void canRequestRootPage() throws IOException {  
// arrange
before((request, response) -> {
});
Server.main(null);
after((request, response) -> {
});
Spark.awaitInitialization();
// act
Document doc = Jsoup.connect("http://localhost:4567/").get();
// assert
Assert.assertNotNull(doc);
Assert.assertTrue(doc.toString().contains("Hello from MainController"));
// clean up 

增加代码到MainController类中
public MainController() {  
get("/", (req, res) -> {
    return "Hello from MainController.";
});
}  

4,到目前为止,我们有controller来处理我们的请求了。而且我们有对应的测试用例证明我们能像我们预期的那样处理这些请求。 但是, 当我们尝试运行我们的服务器,这个服务器并不知道MainController类。那么现在让我们来完善它。修改Server类中为:
package tutorial;
public class Server {
public static void main(String[] args) {
    new MainController();
}
}  

5,最后,让我们来完成pom.xml文件。增加以下内到</dependencies>元素后面。
<build>  
<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
            <source>1.8</source>
            <target>1.8</target>
        </configuration>
    </plugin>
    <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <executions>
            <execution>
                <id>bin</id>
                <phase>package</phase>
                <goals>
                    <goal>single</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
            <archive>
                <manifest>
                    <mainClass>tutorial.Server</mainClass>
                </manifest>
            </archive>
        </configuration>
    </plugin>
</plugins>
</build>  

6,现在,你应该可以运行mvn clean install来成功构建这个项目。

7,我们将可以构建带有这个应用的镜像
构建镜像。
docker build -t bdparrish/docker-spark-tutorial . 

运行这个镜像的容器。注意我们增加了-p参数来暴露我们应用的端口。
docker run -it -p 4567:4567 bdparrish/docker-spark-tutorial 

从log中你应该能看到Java Spark启动了Jetty服务器在4567端口上

8,我们可以通过浏览这个web应用的根地址来验证这个容器
获取IP地址。
docker inspect <container-id> | grep IPAddress

浏览这个web url
http://192.168.99.100:4567/ 

我们应该能看到一个页面展示"Hello from MainController"

9,最后,这个项目可以在这个git分支找到:git checkout add-java-spark-handler

结束语

要获得第一部分所有的内容,可以执行git checkout add-java-spark-handler。在第二部分中,我们将给这个原型增加一个DAO和数据数据库。

参见: 在Docker中运行Java Spark – 第二部分

原文链接:RUNNING JAVA SPARK IN DOCKER - PART 1(翻译:邱戈川)

0 个评论

要回复文章请先登录注册