写点什么

Docker 下的 Spring Cloud 三部曲之二:细说 Spring Cloud 开发

作者:程序员欣宸
  • 2022 年 5 月 07 日
  • 本文字数:8990 字

    阅读完需:约 29 分钟

Docker下的Spring Cloud三部曲之二:细说Spring Cloud开发

欢迎访问我的 GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos


本篇概览

  • 本文是《Docker 下的 Spring Cloud 三部曲》系列的第二篇,详细讲解上一篇实例中用到的 eureka、provider、consumer 等三个应用的开发过程;

环境信息

  • 回顾一下实战环境,如下图:


源码地址

  • 上图的 eureka、provider、consumer 是三个 spring boot 的 web 工程,源码可以在 GitHub 下载,地址和链接信息如下表所示:



  • 这个 git 项目中有多个工程,本次实战的工程是 springcloudscaledemo,如下图红框所示:


如何将 spring boot 工程构建成 docker 镜像

  • 如果您想了解如何将 spring boot 工程构建 docker 镜像,欢迎访问以下三篇实战文章:


  1. 《maven构建docker镜像三部曲之一:准备环境》

  2. 《maven构建docker镜像三部曲之二:编码和构建镜像》;

  3. 《maven构建docker镜像三部曲之三:推送到远程仓库(内网和阿里云)》;


  • 本次实战用到的知识点主要集中在上面的第二部;

开发环境

  • 本次实战开发环境的具体信息如下:


  1. 操作系统:Ubuntu16;

  2. Docker 版本:17.03.2-ce;

  3. JDK:1.8.0_151;

  4. maven:3.3.3;


  • 接下来我们依次开发 eureka、provider、consumer 等三个应用;

eureka-server 应用的 pom.xml

  • 新建一个名为 eureka-server 的 spring boot 应用,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/xsd/maven-4.0.0.xsd">  <modelVersion>4.0.0</modelVersion>
<groupId>com.bolingcavalry</groupId> <artifactId>eureka-server</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging>
<name>eureka-server</name> <description>Demo project for Spring Boot</description>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Edgware.SR1</spring-cloud.version> </properties>
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin>
<!--新增的docker maven插件--> <plugin> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.4.12</version> <!--docker镜像相关的配置信息--> <configuration> <!--镜像名,这里用工程名--> <imageName>bolingcavalry/${project.artifactId}</imageName> <!--TAG,这里用工程版本号--> <imageTags> <imageTag>${project.version}</imageTag> </imageTags> <!--镜像的FROM,使用java官方镜像--> <baseImage>java:8u111-jdk</baseImage> <!--该镜像的容器启动后,直接运行spring boot工程--> <entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint> <!--构建镜像的配置信息--> <resources> <resource> <targetPath>/</targetPath> <directory>${project.build.directory}</directory> <include>${project.build.finalName}.jar</include> </resource> </resources> </configuration> </plugin> </plugins> </build></project>
复制代码


  • pom.xml 中的几个关键点如下:


  1. spring cloud 的版本是 Edgware.SR1;

  2. 添加 spring-cloud-starter-eureka-server 的依赖;

  3. 添加 spring-cloud-dependencies 的依赖(pom 的形式);

  4. 添加插件 docker-maven-plugin,用于将当前工程制作成本地 docker 镜像;

eureka-server 应用的源码

  • eureka-server 应用只有一个 java 文件,内容如下:


package com.bolingcavalry.eurekaserver;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication@EnableEurekaServerpublic class EurekaServerApplication {
public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); }}
复制代码


  • 注意要添加**@EnableEurekaServer**注解;

eureka-server 的配置信息

  • 配置信息 application.properties 的内容如下:


server.port=8080
eureka.instance.hostname=localhosteureka.client.register-with-eureka=falseeureka.client.fetch-registry=falseeureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
复制代码

构建 eureka-server 应用的 docker 镜像

  • 在 pom.xml 文件所在目录下,执行如下命令可以构建 docker 镜像:


mvn clean package -U -DskipTests docker:build
复制代码


  • 构建成功后,执行命令 docker images 可见新构建的镜像,如下:


ubuntu@VM-129-56-ubuntu:~$ sudo docker imagesREPOSITORY                       TAG                 IMAGE ID            CREATED             SIZEbolingcavalry/eureka-server      0.0.1-SNAPSHOT      80663220a5f5        35 hours ago        683 MBbolingcavalry/eureka-server      latest              80663220a5f5        35 hours ago        683 MB
复制代码


  • eureka-server 的镜像 OK 后,我们接下来构建 provide 的镜像;

provider 应用的 pom.xml

  • 新建一个名为 service-provider 的 spring boot 应用,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/xsd/maven-4.0.0.xsd">  <modelVersion>4.0.0</modelVersion>
<groupId>com.bolingcavalry</groupId> <artifactId>service-provider</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging>
<name>service-provider</name> <description>Demo project for Spring Boot</description>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Edgware.SR1</spring-cloud.version> </properties>
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin>
<!--新增的docker maven插件--> <plugin> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.4.12</version> <!--docker镜像相关的配置信息--> <configuration> <!--镜像名,这里用工程名--> <imageName>bolingcavalry/${project.artifactId}</imageName> <!--TAG,这里用工程版本号--> <imageTags> <imageTag>${project.version}</imageTag> </imageTags> <!--镜像的FROM,使用java官方镜像--> <baseImage>java:8u111-jdk</baseImage> <!--该镜像的容器启动后,直接运行spring boot工程--> <entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint> <!--构建镜像的配置信息--> <resources> <resource> <targetPath>/</targetPath> <directory>${project.build.directory}</directory> <include>${project.build.finalName}.jar</include> </resource> </resources> </configuration> </plugin> </plugins> </build></project>
复制代码

provider 应用的源码

  • 入口类 ServiceProviderApplication 的源码如下:


package com.bolingcavalry.serviceprovider;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient@SpringBootApplicationpublic class ServiceProviderApplication { public static void main(String[] args) { SpringApplication.run(ServiceProviderApplication.class, args); }}
复制代码


  • 注意要添加**@EnableDiscoveryClient**注解;

  • 只有一个 controller 类 UserController ,对外提供 http 服务:


@RestControllerpublic class UserController {    @RequestMapping(value = "/getuserinfo/{id}", method = RequestMethod.GET)    public String getUserInfo(@PathVariable String id){        return String.format("user[%s]", id);    }
@RequestMapping(value = "/getuserinfo", method = RequestMethod.GET) public String getUserInfoWithRequestParam(@RequestParam("id") String id, @RequestParam("name") String name){ return String.format("user [%s], id [%s], from server [%s]", name, id, getIPAddr()); }
/** * 获取本机IP地址 * @return */ private static String getIPAddr(){ String hostAddress = null; try{ InetAddress address = InetAddress.getLocalHost(); hostAddress = address.getHostAddress(); }catch (UnknownHostException e){ e.printStackTrace(); }
return hostAddress; }}
复制代码


  • 上面的 controller 提供两个 http 服务,getUserInfoWithRequestParam 服务会返回应用所在机器的 IP 地址;

provider 的配置信息

  • provider 的配置信息存放在 application.yml 文件中,内容如下:


server:  port: 8080spring:  application:    name: microservice-provider-usereureka:  client:    serviceUrl:      defaultZone: http://eurekahost:8080/eureka/  instance:    prefer-ip-address: true
复制代码


  • 注意上面配置的注册中心地址为 http://eurekahost:8080/eureka/,eurekahost 在 docker-compose 中会作为 link 参数对应 eureka server;

构建 provider 应用的 docker 镜像

  • 在 pom.xml 文件所在目录下,执行如下命令可以构建 docker 镜像:


mvn clean package -U -DskipTests docker:build
复制代码


  • 构建成功后,执行命令 docker images 可见新构建的镜像,如下:


ubuntu@VM-129-56-ubuntu:~$ sudo docker imagesREPOSITORY                       TAG                 IMAGE ID            CREATED             SIZEbolingcavalry/eureka-server      0.0.1-SNAPSHOT      80663220a5f5        35 hours ago        683 MBbolingcavalry/eureka-server      latest              80663220a5f5        35 hours ago        683 MBbolingcavalry/service-provider   0.0.1-SNAPSHOT      a02f307bc1a9        22 hours ago        683 MBbolingcavalry/service-provider   latest              a02f307bc1a9        22 hours ago        683 MB
复制代码


  • provider 已经 OK,接下来是 consumer 工程;

consumer 应用的 pom.xml

  • 新建一个名为 service-consumer 的 spring boot 应用,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/xsd/maven-4.0.0.xsd">  <modelVersion>4.0.0</modelVersion>
<groupId>com.bolingcavalry</groupId> <artifactId>service-consumer</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging>
<name>service-consumer</name> <description>Demo project for Spring Boot</description>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Edgware.SR1</spring-cloud.version> </properties>
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin>
<!--新增的docker maven插件--> <plugin> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.4.12</version> <!--docker镜像相关的配置信息--> <configuration> <!--镜像名,这里用工程名--> <imageName>bolingcavalry/${project.artifactId}</imageName> <!--TAG,这里用工程版本号--> <imageTags> <imageTag>${project.version}</imageTag> </imageTags> <!--镜像的FROM,使用java官方镜像--> <baseImage>java:8u111-jdk</baseImage> <!--该镜像的容器启动后,直接运行spring boot工程--> <entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint> <!--构建镜像的配置信息--> <resources> <resource> <targetPath>/</targetPath> <directory>${project.build.directory}</directory> <include>${project.build.finalName}.jar</include> </resource> </resources> </configuration> </plugin> </plugins> </build></project>
复制代码


  • 和前面两个应用相比,这里要引入 spring-cloud-starter-feign

consumer 的源码

  • 入口类 ServiceConsumerApplication 源码如下:


package com.bolingcavalry.serviceconsumer;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.netflix.feign.EnableFeignClients;
@EnableDiscoveryClient@SpringBootApplication@EnableFeignClientspublic class ServiceConsumerApplication {
public static void main(String[] args) { SpringApplication.run(ServiceConsumerApplication.class, args); }}
复制代码


  • 注意要增加**@EnableDiscoveryClient @SpringBootApplication**这两个注解;

  • 增加一个带注解**@FeignClient**的接口,用于在 spring cloud 环境中声明远程调用信息:


@FeignClient(name = "microservice-provider-user")public interface UserFeignClient {
@RequestMapping(value = "/getuserinfo", method = RequestMethod.GET) String getUserInfoWithRequestParam(@RequestParam("id") String id, @RequestParam("name") String name);}
复制代码


  • 增加一个 controller 类 UserFacadeController,为浏览器访问提供 http 服务,并且在响应请求的时候会通过 UserFeignClient 接口的实现远程调用 provider 应用的服务:


@RestControllerpublic class UserFacadeController {
@Autowired private UserFeignClient userFeignClient;
@GetMapping("/user/{id}/{name}") public String getUserInfo(@PathVariable("id") final String id, @PathVariable("name") final String name) { return "1. ---" + userFeignClient.getUserInfoWithRequestParam(id, name); }}
复制代码

consumer 的配置信息

  • provider 的配置信息存放在 application.yml 文件中,内容如下:


server:  port: 8080spring:  application:    name: service-consumereureka:  client:    serviceUrl:      defaultZone: http://eurekahost:8080/eureka/  instance:    prefer-ip-address: true
复制代码


  • 注意上面配置的注册中心地址为 http://eurekahost:8080/eureka/,eurekahost 在 docker-compose 中会作为 link 参数对应 eureka server;

构建 provider 应用的 docker 镜像

  • 在 pom.xml 文件所在目录下,执行如下命令可以构建 docker 镜像:


mvn clean package -U -DskipTests docker:build
复制代码


  • 构建成功后,执行命令 docker images 可见新构建的镜像,如下:


ubuntu@VM-129-56-ubuntu:~$docker imagesREPOSITORY                       TAG                 IMAGE ID            CREATED             SIZEbolingcavalry/service-provider   0.0.1-SNAPSHOT      a02f307bc1a9        47 hours ago        683 MBbolingcavalry/service-provider   latest              a02f307bc1a9        47 hours ago        683 MBbolingcavalry/service-consumer   0.0.1-SNAPSHOT      ae6b37b99754        2 days ago          683 MBbolingcavalry/service-consumer   latest              ae6b37b99754        2 days ago          683 MBbolingcavalry/eureka-server      0.0.1-SNAPSHOT      80663220a5f5        2 days ago          683 MBbolingcavalry/eureka-server      latest              80663220a5f5        2 days ago          683 MB
复制代码


  • 至此,本次实战所需的所有镜像都制作完毕,相关的 demo 工程的开发过程我们也一起过了一遍,上一章中的实战您已经可以独立做出来了,接下来的实战中,我们一起来尝试服务横向扩容;

欢迎关注 InfoQ:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...

发布于: 2022 年 05 月 07 日阅读数: 23
用户头像

搜索"程序员欣宸",一起畅游Java宇宙 2018.04.19 加入

前腾讯、前阿里员工,从事Java后台工作,对Docker和Kubernetes充满热爱,所有文章均为作者原创,个人Github:https://github.com/zq2599/blog_demos

评论

发布
暂无评论
Docker下的Spring Cloud三部曲之二:细说Spring Cloud开发_Java_程序员欣宸_InfoQ写作社区