且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Spring Boot与Docker(三):构建你的第一个微服务和相关容器以及容器的连接

更新时间:2022-09-24 20:57:57

本文讲的是Spring Boot与Docker(三):构建你的第一个微服务和相关容器以及容器的连接【编者的话】本篇是《使用Spring Boot和Docker构建微服务架构》系列的第三篇,本篇我们将会准备开始构建一个员工对象微服务。原文作者为3Pillar环球旗下美国Adbanced技术集团的总监Dan Greene,Dan有十八年的软件设计和开发经验,包括在电子商务、B2B集成、空间分析、SOA架构、大数据以及云计算等领域的软件产品架构经验,他是AWS认证解决方案架构师,在3Pillar之前先后就职于Oracle、ChoicePoint和Booz Allen Hamilton。Dan毕业于乔治·华盛顿大学,他也是一个父亲、业余木工爱好者,还参加过包括国际障碍大赛这样的障碍赛跑。

本篇构建微服务的步骤如下:
  • 建立一个新的Spring Boot工程
  • 定义我们的员工对象
  • 持久连接
  • 公开Web服务
  • 定义一个Docker容器来运行我们的微服务,包括连接到我们在第二篇中创建的Mongo容器
  • 在稍早设置的Docker Machine中运行我们的容器

建立我们的Spring Boot工程
我们将在我们的工程根目录下创建一个文件夹(生产环境中是在一个单独的版本库中)来承载我们的服务,在这个文件夹中,我们将创建build.grade文件。Spring Boot的优势就是在于对于依赖定义非常纯粹,如魔法般地带来了大量的互操作性。我们的build.grade文件看起来如下:
buildscript {
repositories {
jcenter()
}
dependencies { 
classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.2.0.RELEASE'
}
}
apply plugin: 'spring-boot'

repositories { jcenter()
}
dependencies {
compile "org.springframework.boot:spring-boot-starter-actuator"
compile "org.springframework.boot:spring-boot-starter-web"
}

现在,正如我们提到的,我们将使用IDE,具体地说就是Spring Tool Suite(STS),所以我们将增加对于Gradle的支持。首先,打开STS,接着在打开的Dashboard页面上点击“IDE Extensions”的链接:
Spring Boot与Docker(三):构建你的第一个微服务和相关容器以及容器的连接

在屏幕上选择“Grade Support”,点击“Install”,按照提示完成安装,其中包括重启STS:
Spring Boot与Docker(三):构建你的第一个微服务和相关容器以及容器的连接

重启之后,选择“Import project…”,接着选择Gradle project(现在可用了),指向你的目录,然后点击“Build Model”——这将会用“Employee”来产生项目列表——选择这个列表并且点击“Finish”,这将会导入一个简单的build.grade到我们启动的工程。一旦工程被导入之后,第一个将是Spring Boot配置类,在这个场景中,我们将按照他们的服务来命名,所以在这种情况下配置类将会命名为EmployeeBoot。Spring大量使用了注解和反射,所以最小的配置也是需要的(忽略导入):
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class EmployeeBoot {

   public static void main(String[] args) {
        SpringApplication.run(EmployeeBoot.class);
    }
}

我们的Employee类
接下来,我们将使得我们的POJO类来持有员工信息,我们目前保持最少的字段,有必要的话我们将增加:
Employee.Class

@Document(collection=”employees”)
public class Employee {

@Id
private String id; 

private String email;
private String fullName;
private String managerEmail;

// getters and setters omitted for brevity
}

注意@Document这个注解——这会将这个对象连结为一个Mongo文档,并为该Employee“文档”在哪里存储指定了集合名字。
接下来我们将定义一个Spring持久类来读取这些Employee:
EmployeeRepository.class:
public interface EmployeeRepository extends
MongoRepository<Employee, String> {
}

Spring框架的一个优美之处就是在于所有你需要写的——比如扩展自MongoRepository的接口甚至不需要手动编写实现代码。两个通用的参数中第一个表示需要持久化的对象类型(Employee),第二个表示唯一的标识符类型(String类型)。Spring框架将会自动提供所声明的功能95%的实现。接下来的问题就是:Spring如何知道数据库的位置?Spring默认情况下将会寻找localhost:27017,这显然是不会工作的,所以我们需要直接设置位置新型。我们可以实现自己的Mongo模板Bean,但是幸运的是Spring允许我们通过Java属性表传递连接信息。我们可以定义一个属性文件或者在命令行上传递进来。我们选择了后者因为当稍后构建我们的容器时命令行方式非常方便。最后我们需要创建的是一个或者两个Rest端点并确保它们可以工作。我们将构建一个快速的Spring Controller,然后我们就可以测试了。
EmployeeController.java

@RestController
@RequestMapping("/employee")
public class EmployeeController {

@Autowired
EmployeeRepository employeeRepository;

@RequestMapping(method = RequestMethod.POST)
public Employee create(@RequestBody Employee employee){

    Employee result = employeeRepository.save(employee);
    return result;
}

@RequestMapping(method = RequestMethod.GET, value="/{employeeId}")
public Employee get(@PathVariable String employeeId){
    return employeeRepository.findOne(employeeId);
}
}

最开始的@RestController和@RequestMapping这两个类级别的注解告诉Spring框架需要公开这是一个接收JSON的Rest服务,并且公开了URI路径是/employee。@Autowired注解告诉Spring框架采用上面我们定义的Repository接口的自动生成实现代码并将其注入到这个Controller中。现在到了特定的操作——方法级别的@RequestMapping注解表明这个方法将会基于HTTP动词来使用(在本例中是POST和GET),另外对于GET操作,我们指明了一个URL路径{employee},比如使用/employee/abcd1234来寻找一个员工并且返回该值。
现在我们有了足够多的准备工作可以来测试了,第一点,我们需要编译和运行我们的Spring Boot应用,在Eclipse中有很多方法可以做到这一点,但是我们将从命令行开始,并以我们的方式工作。在你的Employee目录中,敲入:gradle build,这个命令将会编译Spring Boot应用到build/lib/Employee.jar,这个jar包包含了运行这个应用所需要的所有东西,包括一个嵌入式的Servlet容器(默认情况下是Tomcat)。
在我们运行和测试这个应用之前,我们需要稍作回顾——我们的Mongo服务又在哪里?观察“docker ps”命令的输出,我们记得虚拟机的32777端口映射到了Mongo容器的27017端口,虚拟机的IP地址是192.126.99.100。如前所述,我们可以通过传递一个环境变量属性的方式来把连接属性传递给Spring,所以运行这个应用的命令行如下:
java -Dspring.data.mongodb.uri=mongodb://192.168.99.100:32777/micros -jar build/libs/Employee.jar

一旦应用启动之后(应该在1~4秒),你可以使用选项中的Rest工具来打开Web服务。

Spring Boot与Docker(三):构建你的第一个微服务和相关容器以及容器的连接

不要忘了在HTTP头部包含值为“application/json”的“Content-Type”,你应该收到如下的响应(id的值取决于你自己的情况):
{
"id": "55fb2f1930e07c6c844b02ff",
"email": "dan.greene@3pillarglobal.com",
"fullName": "Daniel Greene",
"managerEmail": null
}

你可以通过如下的调用测试我们的GET方法:
http://localhost:8080/employee/55fb2f1930e07c6c844b02ff

你应该得到相同的文档,万岁!我们的服务起作用了!

将Boot应用导入容器
现在我们需要构建我们的第一个容器来运行我们的Employee微服务。我们的途径是定义一个Dockerfile,这个文件将会定义如何生成一个镜像并放入我们的精益求精、短小精悍的微服务中。让我们阅读这个文件并逐步解析(参考第三篇第三步请跳到这儿):
FROM java:8
VOLUME /tmp
ADD build/libs/Employee.jar app.jar
EXPOSE 8080
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Dspring.data.mongodb.uri=mongodb://mongodb/micros", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

  • 我们从一个包含了安装了Java 8的标准镜像(镜像名字为“Java”,标签为“8”)开始构建过程
  • 我们接着定义了一个名为/tmp的卷
  • 接着将本地文件系统的一个文件添加进来,并且重命名为“app.jar”,重命名不是必须的,只是一个可用的可选项
  • 我们声明想要公开容器的8080端口
  • 在容器内运行一个touch命令,这样可以确保app.jar文件的修改日期
  • ENTRYPOINT命令定义了容器启动时需要运行的内容——我们运行Java,设置我们的Spring Mongo属性,还有快速的附加属性来加速Tomcat启动时间,然后指向我们的jar包。

现在我们通过运行如下命令构建镜像:
docker build -t microservicedemo/employee . 

我们可以敲入docker images看到结果
REPOSITORY                  TAG             IMAGE ID            CREATED             VIRTUAL SIZE
microservicedemo/employee   latest          364ffd8162b9        15 minutes ago      846.6 MB


接下来的问题就是“我们的服务容器如何与Mongo容器交互?”,为此,我们引入了容器的link机制。当你运行一个新的容器时,你可以传入一个可选的-link参数指定一个运行中的容器的名字,这样新的容器就可以与这个容器通讯了,所以我们的命令是:
docker run -P -d --name employee --link mongodb microservicedemo/employee


我们启动了一个新的容器,公开了端口(-P),以后台方式运行(-d),命名为employee(—name),接着将这个新的容器连接到了一个名为“mongodb”的容器(-link),连接过程如下:
  • 在employee容器的host文件添加一个条目指向MongoDB容器的运行位置
  • 在employee容器内添加一些环境变量来协助其他必要的编程访问,可以运行如下命令查看: {{{docker exec employee bash -c 'env | grep MONGODB'}}}
  • 允许容器通过公开的端口来直接通讯,这样就不需要担心主机的部分映射了。如果你还记得上述的内容,我们设置了Spring Mongo到MongoDB的URL作为主机名(mongodb://mongodb/micros),所以有了host文件条目和运行在默认端口的Mongo,Boot应用容器可以连上数据库了

在容器运行时我们可以来执行相同的Web服务,只是这次是作为容器来运行的(对于我来说,容器的8080端口会被映射到虚拟机的32772端口):
Spring Boot与Docker(三):构建你的第一个微服务和相关容器以及容器的连接

本篇我们已经取得了很大的进展,我们有了两个容器可以工作并且可以互相通讯,接下来的第四篇我们将添加一些额外的服务/容器,可以观察到构建更新的进度并与CI工具集成工作。

原文链接:BUILDING A MICROSERVICE ARCHITECTURE WITH SPRING BOOT AND DOCKER, PART III(翻译:胡震)

原文发布时间为:2015-12-14
本文作者:国会山上的猫TuxHu
本文来自云栖社区合作伙伴DockerOne,了解相关信息可以关注DockerOne。
原文标题:Spring Boot与Docker(三):构建你的第一个微服务和相关容器以及容器的连接