本文代码请参考《https://github.com/478632418/springcloud-eureka-server-client/tree/master/mall》、《https://github.com/478632418/springboot-eureka

本章节主要包含SpringCloud终端服务器注册中心、服务提供者、服务器消费几个角色的项目创建示例。

我们这里选取Euerka作为服务注册发现框架,实际上能提供服务注册与发现的框架并不止它一个,但是业界内使用这个还比较广泛,但是有人说它从2.0之后Netflix就不在维护它了,但是依然有不少公司还坚持选了它,因为它到2.0就已经很稳定了。

Eureka注册中心简介

Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。

Eureka包含两个组件:Eureka Server和Eureka Client。

Eureka Server:提供服务注册服务,服务启动后,服务会在Eureka Server中进行注册,包括主机与端口号、服务版本号、通信协议等。这样Eureka Server中的服务注册表中将会存储所有可用的服务节点的信息,服务节点的信息可以在界面中直观的看到。

Eureka Server端支持集群模式部署,首尾相连形成一个闭环即可,集群中的不同服务注册中心通过异步模式互相复制各自的状态,这也意味着在给定的时间点每个实例中存储的所有服务的状态可能存在不一致的现象。

Eureka Client:主要处理服务的注册和发现。客户端服务通过注册和参数配置的方式,嵌入在客户端应用程序的代码中。在应用程序启动时,Eureka客户端向服务注册中心注册自身提供的服务,并周期性的发送心跳来更新它的服务租约。同时,它也能从服务端查询当前注册的服务信息并把它们缓存到本地并周期性的刷新服务状态。

服务调用:

服务消费者在获取服务清单后,通过服务名可以获取具体提供服务的实例名和该实例的元数据信息。因为有这些服务实例的详细信息,所以客户端可以根据自己的需求决定具体调用哪个实例,在Ribbon中会默认采用轮询的方式进行调用,从而实现客户端的负载均衡。

服务提供者与服务消费者之间调用关系:

1)服务注册中心启动;

2)服务提供者在启动时,向注册中心注册自己提供的服务;

3)服务消费者在启动时,向注册中心订阅自己所需要的服务;

4)注册中心返回服务提供者地址给消费者;

5)服务消费者从提供者地址中调用消费者。

实际上在开发中过程中Eureka Server就是注册中心;Eureka Client就是服务提供者和消费者。

根项目创建:

SpringCloud是要基于SpringBoot的,因此在根项目导入了SpringBoot的parent引用。

    <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>

根项目命名为mall,它包含了三个主要子模块(,config是配置中心的一个实现,放在下一篇文章中学习):

server(maven module):Eureka Server(服务注册中心)

provider(maven module):Eureka Client(服务提供者)+Actuator(服务器监控)

consumer(maven module):Eureka Client(服务器消费者)+Ribbon(负载均衡)+Actuator(服务器监控)

Eureka-Server

在上边新建的Maven Project下新建server项目(maven module). server project就是服务注册中心,这里讲会讲解采用分布式配置以及如何运行在docker container中。

1)修改server project的pom.xml

maven项目的名称为server,版本号为1.0.0

    <parent>
<groupId>com.dx.mall</groupId>
<artifactId>mall</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.mall</groupId>
<artifactId>server</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>server</name>
<description>mall-server</description>

引入springboot-web引用,因为springcloud需要依赖于springboot,我们这里作为web项目因此引用springboot-web。

    <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-cloud.version>Finchley.SR2</spring-cloud.version>
<docker.image.prefix>mall</docker.image.prefix>
<java.version>1.8</java.version>
<skipTests>true</skipTests>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</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>

上边是springboot-web和eureka-server和dependencyManagement是必须的,然后引入docker-build maven插件,以来Dockerfile来实现生成image到docker。

    <!--
使用maven插件的install执行时,会自动创建、更新images。
使用时需要在根目录下包含Dockerfile文件,否则会抛出异常。
-->
<build>
<finalName>server</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<repository>${docker.image.prefix}/${project.build.finalName}</repository>
<tag>${version}</tag>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>

finalName中制定了打包的包名,上边plugins下包含两个maven plugin,第一个是spring-boot maven编译器,第二个就docker插件,构造docker image使用,需要在服务器端安装docker。

为了防止找不到包,引入maven仓库。

    <!-- 解决maven仓库找不到jar问题 -->
<repositories>
<repository>
<id>spring-milestone-repo</id>
<url>http://repo.spring.io/milestone/</url>
</repository>
</repositories>

2)application.yml文件配置

application.yml中配置内容如下:

spring:
application:
name: mall-server eureka:
# 关闭自我保护模式
# eureka.server.enable-self-preservation: false
instance:
prefer-ip-address: true
lease-expiration-duration-in-seconds: 30
lease-renewal-interval-in-seconds: 30
client:
registerWithEureka: false
fetchRegistry: false
healthcheck:
enabled: true
service-url:
defaultZone: http://slave1:8761/eureka/,http://slave2:8762/eureka/,http://slave3:8763/eureka/
server:
enable-self-preservation: true
info:
app:
name: ${spring.application.name}
description: Eureka 注册中心
version: 1.0.0 ---
spring:
profiles:
slave1
server:
port: 8761
eureka:
instance:
hostname: slave1 ---
spring:
profiles:
slave2
server:
port: 8762
eureka:
instance:
hostname: slave2 ---
spring:
profiles:
slave3
server:
port: 8763
eureka:
instance:
hostname: slave3

这里相当于使用三个yml文件:application-slave1.yml,application-slave2.yml,application-slave3.yml(用法参考:https://docs.spring.io/spring-boot/docs/2.1.10.BUILD-SNAPSHOT/reference/html/howto-properties-and-configuration.html#howto-change-configuration-depending-on-the-environment)。只是配置方式不同罢了,这么做的目的是为了更方便在docker上部署分布式eureka-server。实际上就是使用docker-compose(docker重排功能)实现分布式部署。

其中info:下是actuator依赖配置为了在euerka-server ui中展示更有用详细信息,通过/info等地质访问到的信息。

其中eureka:client中展示的信息是是否注册自身等配置,service-url:defaultZone是用来eureka-server一起组成集群使用的,这个是必须配置的。

3)编写入口类(com.mall.server.ServerApplication):

package com.mall.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; /**
* 注册中心
*
* @version 1.0.0
*/
@EnableEurekaServer
@SpringBootApplication
public class ServerApplication { public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}

其中@SpringBootApplicaiton是springboot项目中,制定项目启动入口注解;

其中@EnableEurekaServer是注解该project为Eureka-Server。

4)在server的根下创建Dockerfile

Dockerfile是docker maven plugin生成image时需要依赖的文件,否则无法正确生成image,Dockerfile中配置信息如下:

# 基于哪个镜像
FROM java:8
# 将本地文件夹挂载到当前容器
VOLUME /tmp
# 拷贝文件到容器,server.jar这里是maven打包后的名字
ADD ./target/server.jar app.jar
RUN bash -c 'touch /app.jar'
# 配置容器启动后执行的命令
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

5)使用maven工具生成docker image

在eclipse中选中该server项目-》Run As-》Maven install进行项目编译:

[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for com.mall:server:jar:1.0.0
[WARNING] The expression ${version} is deprecated. Please use ${project.version} instead.
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] --------------------------< com.mall:server >---------------------------
[INFO] Building server 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ server ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ server ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ server ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ server ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ server ---
[INFO] Tests are skipped.
[INFO]
[INFO] --- maven-jar-plugin:3.1.0:jar (default-jar) @ server ---
[INFO] Building jar: /Users/dz/work/springcloud-test/mall/server/target/server.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.1.1.RELEASE:repackage (repackage) @ server ---
[INFO] Replacing main artifact with repackaged archive
[INFO]
[INFO] --- dockerfile-maven-plugin:1.4.0:build (build-image) @ server ---
[INFO] Building Docker context /Users/dz/work/springcloud-test/mall/server
[INFO]
[INFO] Image will be built as mall/server:1.0.0
[INFO]
[INFO] Step 1/5 : FROM java:8
[INFO]
[INFO] Pulling from library/java
[INFO] Image 5040bd298390: Pulling fs layer
...
[INFO] Image bb9cdec9c7f3: Extracting
[INFO] Image bb9cdec9c7f3: Pull complete
[INFO] Digest: sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9d
[INFO] Status: Downloaded newer image for java:8
[INFO] ---> d23bdf5b1b1b
[INFO] Step 2/5 : VOLUME /tmp
[INFO]
[INFO] ---> Running in 44f90f8f1fb1
[INFO] Removing intermediate container 44f90f8f1fb1
[INFO] ---> 13d7c25e8287
[INFO] Step 3/5 : ADD ./target/server.jar app.jar
[INFO]
[INFO] ---> 54ecfa5e791d
[INFO] Step 4/5 : RUN bash -c 'touch /app.jar'
[INFO]
[INFO] ---> Running in bf2cbe1b90f7
[INFO] Removing intermediate container bf2cbe1b90f7
[INFO] ---> 00c1f22288b9
[INFO] Step 5/5 : ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
[INFO]
[INFO] ---> Running in 0c28ddc6d2ce
[INFO] Removing intermediate container 0c28ddc6d2ce
[INFO] ---> b195029b462d
[INFO] [Warning] One or more build-args [JAR_FILE] were not consumed
[INFO] Successfully built b195029b462d
[INFO] Successfully tagged mall/server:1.0.0
[INFO]
[INFO] Detected build of image with id b195029b462d
[INFO] Building jar: /Users/dz/work/springcloud-test/mall/server/target/server-docker-info.jar
[INFO] Successfully built mall/server:1.0.0
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ server ---
[INFO] Installing /Users/dz/work/springcloud-test/mall/server/target/server.jar to /opt/mvn_local_repo/com/mall/server/1.0.0/server-1.0.0.jar
[INFO] Installing /Users/dz/work/springcloud-test/mall/server/pom.xml to /opt/mvn_local_repo/com/mall/server/1.0.0/server-1.0.0.pom
[INFO] Installing /Users/dz/work/springcloud-test/mall/server/target/server-docker-info.jar to /opt/mvn_local_repo/com/mall/server/1.0.0/server-1.0.0-docker-info.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 11:12 min
[INFO] Finished at: 2019-09-23T11:27:43+08:00
[INFO] ------------------------------------------------------------------------

或者

通过mvn命令mvn package来生成images

dx:server $ mvn package -Ddockerfile.skip=false

mvn clean package -Ddockerfile.skip=false

此时查看Docker上的images列表如下:

dx:~ $ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mall/server 1.0.0 b195029b462d 2 hours ago 735MB
java 8 d23bdf5b1b1b 2 years ago 643MB

6)在server项目根下创建docker-componse.yml重新编排文件

version: '3.5'
services:
slave1:
container_name: s1
image: mall/server:1.0.0
networks:
- mall-server-net
ports:
- 8761:8761
environment:
- SPRING_PROFILES_ACTIVE=slave1 slave2:
container_name: s2
image: mall/server:1.0.0
networks:
- mall-server-net
ports:
- 8762:8762
environment:
- SPRING_PROFILES_ACTIVE=slave2 slave3:
container_name: s3
image: mall/server:1.0.0
networks:
- mall-server-net
ports:
- 8763:8763
environment:
- SPRING_PROFILES_ACTIVE=slave3 networks:
mall-server-net:
name: mall-server-net
driver: bridge

重新编排的目的:使用images运行多个实例到container。

执行docker-compose重新编排。

dx:springcloud-test $ cd mall/
dx:mall $ ls
config consumer pom.xml product server src
dx:mall $ cd server/
dx:server $ ls
Dockerfile docker-compose.yml pom.xml src target
dx:server $ docker-compose -f docker-compose.yml up -d
Creating network "mall-server-net" with driver "bridge"
Creating s1 ... done
Creating s2 ... done
Creating s3 ... done
dx:server $ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e4b21fd1eb29 mall/server:1.0.0 "java -Djava.securit…" 6 seconds ago Up 5 seconds 0.0.0.0:8761->8761/tcp s1
9c798524acb1 mall/server:1.0.0 "java -Djava.securit…" 6 seconds ago Up 5 seconds 0.0.0.0:8763->8763/tcp s3
bd047426e71b mall/server:1.0.0 "java -Djava.securit…" 6 seconds ago Up 5 seconds 0.0.0.0:8762->8762/tcp s2
dx:server $

此时访问:http://localhost:8761,http://localhost:8762,http://localhost:8763均可以访问到如下界面:

到这里就说明eureka server已经成功部署并运行。源代码参考:https://github.com/478632418/springcloud-eureka-server-client/tree/master/mall/server

Provider(Eureka-Client)

在maill(maven project)下新建product project(maven module) ,用来实现服务提供者功能。

1)修改server project的pom.xml

maven项目的名称为product,版本号为1.0.0,并引入eureka-client maven依赖。

    <parent>
<groupId>com.dx.mall</groupId>
<artifactId>mall</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.dx.mall.product</groupId>
<artifactId>product</artifactId>
<version>1.0.0</version>
<name>product</name>
<url>http://maven.apache.org</url>

引入springboot-web引用,因为springcloud需要依赖于springboot,我们这里作为web项目因此引用springboot-web。

    <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-cloud.version>Finchley.SR2</spring-cloud.version>
<docker.image.prefix>mall</docker.image.prefix>
<java.version>1.8</java.version>
<skipTests>true</skipTests>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</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>

上边是springboot-web和eureka-client和dependencyManagement是必须的,然后引入docker-build maven插件,用来Dockerfile来实现生成image到docker。

    <!--
使用maven插件的install执行时,会自动创建、更新images。
使用时需要在根目录下包含Dockerfile文件,否则会抛出异常。
-->
<build>
<finalName>product</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<repository>${docker.image.prefix}/${project.build.finalName}</repository>
<tag>${version}</tag>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>

finalName中制定了打包的包名,上边plugins下包含两个maven plugin,第一个是spring-boot maven编译器,第二个就docker插件,构造docker image使用,需要在服务器端安装docker。

为了防止找不到包,引入maven仓库。

    <!-- 解决maven仓库找不到jar问题 -->
<repositories>
<repository>
<id>spring-milestone-repo</id>
<url>http://repo.spring.io/milestone/</url>
</repository>
</repositories>

2)application.yml文件配置

application.yml中配置内容如下:

spring:
application:
name: spring-cloud-producer eureka:
client:
service-url:
defaultZone: http://slave1:8761/eureka/,http://slave2:8762/eureka/,http://slave3:8763/eureka/
instance:
preferIpAddress: true info:
app:
name: ${spring.application.name}
description: Spring-Cloud-Producer
version: 1.0.0
build.artifactId: $project.artifactId$
build.version: $project.version$ ---
spring:
profiles:
slave1
server:
port: 7761
eureka:
instance:
hostname: slave1 ---
spring:
profiles:
slave2
server:
port: 7762
eureka:
instance:
hostname: slave2 ---
spring:
profiles:
slave3
server:
port: 7763
eureka:
instance:
hostname: slave3

这里相当于使用三个yml文件:application-slave1.yml,application-slave2.yml,application-slave3.yml。只是配置方式不同罢了,这么做的目的是为了更方便在docker上部署分布式eureka-client服务提供者。实际上就是使用docker-compose(docker重排功能)实现分布式部署。

其中info:下是actuator依赖配置为了在euerka-server ui中展示更有用详细信息,通过/info等地质访问到的信息。

其中eureka:client:service-url:defaultZone是用来eureka-client发现eureka-server使用的,这个是必须配置的。

3)编写入口类(org.product.App):

package org.product;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient; /**
* Hello world!
*
*/
@SpringBootApplication
@EnableEurekaClient
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}

其中@SpringBootApplicaiton是springboot项目中,制定项目启动入口注解;

其中@EnableEurekaClient是注解该project为Eureka-Client。

4)编写服务提供(org.product.controller.DemoController)类

package org.product.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; @RestController
public class DemoController {
@Value("${server.port}")
String serverPort; @GetMapping("/getPortInfo")
public String getPortInfo() {
return "The port is "+serverPort;
} }

5)在product的根下创建Dockerfile

Dockerfile是docker maven plugin生成image时需要依赖的文件,否则无法正确生成image,Dockerfile中配置信息如下:

# 基于哪个镜像
FROM java:8
# 将本地文件夹挂载到当前容器
VOLUME /tmp
# 拷贝文件到容器,product.jar这里是maven打包后的名字
ADD ./target/product.jar product.jar
RUN bash -c 'touch /product.jar'
# 配置容器启动后执行的命令
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/product.jar"]

6)使用maven工具生成docker image

在eclipse中选中该server项目-》Run As-》Maven install进行项目编译:

[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for com.dx.mall.product:product:jar:1.0.0
[WARNING] The expression ${version} is deprecated. Please use ${project.version} instead.
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] --------------------< com.dx.mall.product:product >---------------------
[INFO] Building product 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ product ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ product ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /Users/dz/work/springcloud-test/mall/product/target/classes
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ product ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/dz/work/springcloud-test/mall/product/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ product ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/dz/work/springcloud-test/mall/product/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ product ---
[INFO] Tests are skipped.
[INFO]
[INFO] --- maven-jar-plugin:3.1.0:jar (default-jar) @ product ---
[INFO] Building jar: /Users/dz/work/springcloud-test/mall/product/target/product.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.1.1.RELEASE:repackage (repackage) @ product ---
[INFO] Replacing main artifact with repackaged archive
[INFO]
[INFO] --- dockerfile-maven-plugin:1.4.0:build (build-image) @ product ---
[INFO] Building Docker context /Users/dz/work/springcloud-test/mall/product
[INFO]
[INFO] Image will be built as mall/product:1.0.0
[INFO]
[INFO] Step 1/5 : FROM java:8
[INFO]
[INFO] Pulling from library/java
[INFO] Digest: sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9d
[INFO] Status: Image is up to date for java:8
[INFO] ---> d23bdf5b1b1b
[INFO] Step 2/5 : VOLUME /tmp
[INFO]
[INFO] ---> Using cache
[INFO] ---> 13d7c25e8287
[INFO] Step 3/5 : ADD ./target/product.jar product.jar
[INFO]
[INFO] ---> 7f918fde0731
[INFO] Step 4/5 : RUN bash -c 'touch /product.jar'
[INFO]
[INFO] ---> Running in 368ce696cbd6
[INFO] Removing intermediate container 368ce696cbd6
[INFO] ---> 1fa85ed6c438
[INFO] Step 5/5 : ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/product.jar"]
[INFO]
[INFO] ---> Running in 5049235d2782
[INFO] Removing intermediate container 5049235d2782
[INFO] ---> 614560332af7
[INFO] [Warning] One or more build-args [JAR_FILE] were not consumed
[INFO] Successfully built 614560332af7
[INFO] Successfully tagged mall/product:1.0.0
[INFO]
[INFO] Detected build of image with id 614560332af7
[INFO] Building jar: /Users/dz/work/springcloud-test/mall/product/target/product-docker-info.jar
[INFO] Successfully built mall/product:1.0.0
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ product ---
[INFO] Installing /Users/dz/work/springcloud-test/mall/product/target/product.jar to /opt/mvn_local_repo/com/dx/mall/product/product/1.0.0/product-1.0.0.jar
[INFO] Installing /Users/dz/work/springcloud-test/mall/product/pom.xml to /opt/mvn_local_repo/com/dx/mall/product/product/1.0.0/product-1.0.0.pom
[INFO] Installing /Users/dz/work/springcloud-test/mall/product/target/product-docker-info.jar to /opt/mvn_local_repo/com/dx/mall/product/product/1.0.0/product-1.0.0-docker-info.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 23.690 s
[INFO] Finished at: 2019-09-23T23:38:03+08:00
[INFO] ------------------------------------------------------------------------

或者进入provider项目根目录下,通过mvn命令mvn package来生成images

dx:provider $ mvn package -Ddockerfile.skip=false

mvn clean package -Ddockerfile.skip=false

此时查看Docker上的images列表如下:

dx:server $ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mall/product 1.0.0 614560332af7 About a minute ago 724MB
mall/server 1.0.0 b195029b462d 12 hours ago 735MB
java 8 d23bdf5b1b1b 2 years ago 643MB
dx:server $

出现上边信息说明已经成功生成了mall/product镜像。

6)在product项目根下创建docker-componse.yml重新编排文件

version: '3.5'
services:
slave1:
container_name: p1
image: mall/product:1.0.0
networks:
- mall-server-net
ports:
- 7761:7761
environment:
- SPRING_PROFILES_ACTIVE=slave1 slave2:
container_name: p2
image: mall/product:1.0.0
networks:
- mall-server-net
ports:
- 7762:7762
environment:
- SPRING_PROFILES_ACTIVE=slave2 slave3:
container_name: p3
image: mall/product:1.0.0
networks:
- mall-server-net
ports:
- 7763:7763
environment:
- SPRING_PROFILES_ACTIVE=slave3 networks:
mall-server-net:
name: mall-server-net
driver: bridge

注意:

1)生成该编排文件时,必须要networks和之前server的networks共用一个,否则会导致出现后边eureka-server和服务提供者(product)运行的容器的网段不在一起,进而导致网络无法被访问。

2)重新编排的目的:使用images运行多个实例到container。

执行docker-compose重新编排。

dx:server $ pwd
/Users/dz/work/springcloud-test/mall/server
dx:server $ cd ..
dx:mall $ cd product/
dx:product $ ls
Dockerfile docker-compose.yml pom.xml src target
dx:product $ docker-compose -f docker-compose.yml up -d
Creating p3 ... done
Creating p2 ... done
Creating p1 ... done
dx:product $ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ee3c8c4968eb mall/product:1.0.0 "java -Djava.securit…" 7 seconds ago Up 6 seconds 0.0.0.0:7762->7762/tcp p2
893af08a6d8a mall/product:1.0.0 "java -Djava.securit…" 7 seconds ago Up 6 seconds 0.0.0.0:7763->7763/tcp p3
02bea113a771 mall/product:1.0.0 "java -Djava.securit…" 7 seconds ago Up 6 seconds 0.0.0.0:7761->7761/tcp p1
e4b21fd1eb29 mall/server:1.0.0 "java -Djava.securit…" 10 hours ago Up 10 hours 0.0.0.0:8761->8761/tcp s1
9c798524acb1 mall/server:1.0.0 "java -Djava.securit…" 10 hours ago Up 10 hours 0.0.0.0:8763->8763/tcp s3
bd047426e71b mall/server:1.0.0 "java -Djava.securit…" 10 hours ago Up 10 hours 0.0.0.0:8762->8762/tcp s2
dx:product $

此时访问:http://localhost:8761,http://localhost:8762,http://localhost:8763均可以访问到如下界面:

到这里就说明eureka provider已经成功部署并运行。

Consumer(Eureka-Client)

在mall下新建consumer(maven module)项目,pom.xml版本名称修改:

1)修改server project的pom.xml

maven项目的名称为consumer,版本号为1.0.0,并引入eureka-client maven依赖。

    <parent>
<groupId>com.dx.mall</groupId>
<artifactId>mall</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.dx.mall.consumer</groupId>
<artifactId>consumer</artifactId>
<version>1.0.0</version>
<name>consumer</name>
<url>http://maven.apache.org</url>

引入springboot-web引用,因为springcloud需要依赖于springboot,我们这里作为web项目因此引用springboot-web。

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-cloud.version>Finchley.SR2</spring-cloud.version>
<docker.image.prefix>mall</docker.image.prefix>
<java.version>1.8</java.version>
<skipTests>true</skipTests>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
        <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</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>

上边是springboot-web和eureka-client和dependencyManagement是必须的,然后引入docker-build maven插件,用来Dockerfile来实现生成image到docker。

    <!--
使用maven插件的install执行时,会自动创建、更新images。
使用时需要在根目录下包含Dockerfile文件,否则会抛出异常。
-->
<build>
<finalName>consumer</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<repository>${docker.image.prefix}/${project.build.finalName}</repository>
<tag>${version}</tag>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>

finalName中制定了打包的包名,上边plugins下包含两个maven plugin,第一个是spring-boot maven编译器,第二个就docker插件,构造docker image使用,需要在服务器端安装docker。

为了防止找不到包,引入maven仓库。

    <!-- 解决maven仓库找不到jar问题 -->
<repositories>
<repository>
<id>spring-milestone-repo</id>
<url>http://repo.spring.io/milestone/</url>
</repository>
</repositories>

2)application.yml文件配置

application.yml中配置内容如下:

spring:
application:
name: spring-cloud-consumer
eureka:
client:
service-url:
defaultZone: http://slave1:8761/eureka/,http://slave2:8762/eureka/,http://slave3:8763/eureka/
instance:
preferIpAddress: true
info:
app:
name: ${spring.application.name}
description: Spring-Cloud-Consumer
version: 1.0.
build.artifactId: $project.artifactId$
build.version: $project.version$
#取消Ribbon使用Eureka
#ribbon:
# eureka:
# enabled: true
#配置Ribbon能访问 的微服务节点,多个节点用逗号隔开
#spring-cloud-consumer:
# ribbon:
# listOfServers: localhost:,localhost: ---
spring:
profiles: slave1
server:
port:
management:
port:
health:
mail:
enabled: false
eureka:
instance:
hostname: slave1

这里配置了一个application.yml的标签

3)编写入口类(org.consumer.App):

package org.consumer;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate; /**
* Hello world!
*
*/
@SpringBootApplication
@EnableEurekaClient
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
} @Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
} // 负载均衡策略
@Bean
public IRule myRule() {
return new RandomRule();
}
}
 

其中@SpringBootApplicaiton是springboot项目中,制定项目启动入口注解;

其中@EnableEurekaClient是注解该project为Eureka-Client。

4)编写服务提供(org.consumer.controller.DemoController)类

package org.consumer.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; @RestController
public class RibbonController { @Autowired
RestTemplate restTemplate; @GetMapping("/getProviderInfo")
public String getProviderInfo() {
String result = this.restTemplate.getForObject("http://spring-cloud-producer/getPortInfo", String.class);
        return result;
}
}
 

注意:上边代码中访问provider的url(http://spring-cloud-producer/)其实是 provider项目中application.yml中的配置项spring.application.name配置的值。

5)在product的根下创建Dockerfile

Dockerfile是docker maven plugin生成image时需要依赖的文件,否则无法正确生成image,Dockerfile中配置信息如下:

# 基于哪个镜像
FROM java:8
# 将本地文件夹挂载到当前容器
VOLUME /tmp
# 拷贝文件到容器,consumer.jar这里是maven打包后的名字
ADD ./target/consumer.jar consumer.jar
RUN bash -c 'touch /consumer.jar'
# 配置容器启动后执行的命令
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/consumer.jar"]

6)使用maven工具生成docker image

在eclipse中选中该consumer项目-》Run As-》Maven install进行项目编译就会通过mvn docker插件将生成images到本地docker上。

或者通过mvn命令也行:

进入consumer项目根目录下,通过mvn命令mvn package来生成images

dx:provider $ mvn package -Ddockerfile.skip=false

mvn clean package -Ddockerfile.skip=false

此时查看Docker上的images列表如下:

dx:server $ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mall/product 1.0.0 614560332af7 About 1 hours ago 724MB
mall/server 1.0.0 b195029b462d 12 hours ago 735MB
mall/consumer 1.0.0 iudksjd95029 About a minute ago 733MB
java 8 d23bdf5b1b1b 2 years ago 643MB dx:server $

出现上边信息说明已经成功生成了mall/consumer镜像。

7)在consumer项目根下创建docker-componse.yml重新编排文件,文件内容如下:

version: '3.5'
services:
slave1:
container_name: c1
image: mall/consumer:1.0.
networks:
- mall-server-net
ports:
- :
environment:
- SPRING_PROFILES_ACTIVE=slave1 networks:
mall-server-net:
name: mall-server-net
driver: bridge

通过docker-compose构建container时,这里指定只启动一个cotainer实例。

执行docker-compose重新编排。

dx:server $ pwd
/Users/dz/work/springcloud-test/mall/server
dx:server $ cd ..
dx:mall $ cd consumer/
dx:consumer $ ls
Dockerfile docker-compose.yml pom.xml src target
dx:consumer $ docker-compose -f docker-compose.yml up -d
Creating c1 ... done
dx:consumer $ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ee3c8c4968eb mall/product:1.0.0 "java -Djava.securit…" 1 hours ago Up 1 hours 0.0.0.0:7762->7762/tcp p2
893af08a6d8a mall/product:1.0.0 "java -Djava.securit…" 1 hours ago Up 1 hours 0.0.0.0:7763->7763/tcp p3
02bea113a771 mall/product:1.0.0 "java -Djava.securit…" 1 hours ago Up 1 hours 0.0.0.0:7761->7761/tcp p1
e4b21fd1eb29 mall/server:1.0.0 "java -Djava.securit…" 10 hours ago Up 10 hours 0.0.0.0:8761->8761/tcp s1
9c798524acb1 mall/server:1.0.0 "java -Djava.securit…" 10 hours ago Up 10 hours 0.0.0.0:8763->8763/tcp s3
bd047426e71b mall/server:1.0.0 "java -Djava.securit…" 10 hours ago Up 10 hours 0.0.0.0:8762->8762/tcp s2
ioweu2992333        mall/consumer:1.0.0  "java -Djava.securit…"   7 seconds ago       Up 6 seconds        0.0.0.0:6761->6761/tcp   c1
dx:consumer $

此时说明consumer容器已经启动,访问路径:http://slave1:6761/getProviderInfo

此时可能返回:The port is 7762

刷新后返回信息端口号会变化。

其他资源相同资源可参考:

1)《搜云技术团队-SpringCloud

2)《利用docker、docker-compose部署Eureka集群的完全详细步骤

3)《spring cloud---坏~牧羊人

SpringBoot(十五):SpringBoot2.x集成eureka实现注高可用册中心,高可用的服务器提供者,以及消费者示例的更多相关文章

  1. 面试连环炮系列(十五):说说Eureka的高可用方案

    说说Eureka的高可用方案 至少3个Eureka实例才能满足高可用,配置方法如下: 准备三个节点node1,node2,node3. 在每个实例的application.xml文件里加入 eurek ...

  2. springboot(十五):springboot+jpa+thymeleaf增删改查示例

    这篇文章介绍如何使用jpa和thymeleaf做一个增删改查的示例. 先和大家聊聊我为什么喜欢写这种脚手架的项目,在我学习一门新技术的时候,总是想快速的搭建起一个demo来试试它的效果,越简单越容易上 ...

  3. SpringBoot(十五)_springboot实现预览pdf

    最近,项目上要做个打印的东西,还要预览.我想就直接生成pdf预览,然后用户选择打印 于是,昨天找了找资料.一般用itext 进行转pdf.于是我就用springboot试了试,代码比较简单,现在只是简 ...

  4. shiro实战系列(十五)之Spring集成Shiro

    Shiro 的 JavaBean 兼容性使得它非常适合通过 Spring XML 或其他基于 Spring 的配置机制.Shiro 应用程序需要一个具 有单例 SecurityManager 实例的应 ...

  5. 第十五章:集成JPUSH

    如果不想自己搭建push server,则可以借助于第三方的api来实现push的功能,本文主要介绍ionic如何集成jpush. 具体步骤如下: 创建ionic应用:ionic_jpush. 申请j ...

  6. springboot(十五)-Runner启动器

    Runner启动器 如果你想在Spring Boot启动的时候运行一些特定的代码,你可以实现接口ApplicationRunner或者CommandLineRunner,这两个接口实现方式一样,它们都 ...

  7. SpringCloud微服务实战——搭建企业级开发框架(十五):集成Sentinel高可用流量管理框架【熔断降级】

      Sentinel除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一.由于调用关系的复杂性,如果调用链路中的某个资源不稳定,最终会导致请求发生堆积.Sentinel ...

  8. springboot基础项目搭建(十五篇)

    springboot系列一.springboot产生背景及介绍 springboot系列二.springboot项目搭建 springboot系列三.springboot 单元测试.配置访问路径.多个 ...

  9. springboot 集成eureka 超详细配置

    撸了今年阿里.头条和美团的面试,我有一个重要发现.......>>> 原文链接: https://blog.csdn.net/nanbiebao6522/article/detail ...

随机推荐

  1. Synchronized与ReentrantLock区别总结

    这篇文章是关于这两个同步锁的简单总结比较,关于底层源码实现原理没有过多涉及,后面会有关于这两个同步锁的底层原理篇幅去介绍. 相似点: 这两种同步方式有很多相似之处,它们都是加锁方式同步,而且都是阻塞式 ...

  2. linux-Windows文件上传Linux

    使用Xshell5工具: 1.使用cmd在Windows上压缩文件 2.在Xshell5上使用SSH协议与Linux服务器建立连接 3.新建文件传输 4.切换到Linux文件目录 5.使用put命令进 ...

  3. nginx 常用的location rewrite proxy_pass

    location 以 = 开头,表示精确匹配:如只匹配根目录结尾的请求,后面不能带任何字符串. 以^~ 开头,表示uri以某个常规字符串开头,如果匹配到,则不继续往下匹配.不是正则匹配 以~ 开头,表 ...

  4. springboot设置访问端口和项目路径

    找到,application.properties, 添加如下配置即可 server.port=8088server.servlet.context-path=/

  5. Linux(CentOS7)下安装Mysql8数据库

    一.Linux版本 二.先下载Linux下的Mysql包,打开Mysql官网 https://www.mysql.com/ 点击DOWNLOAD,进入 https://www.mysql.com/do ...

  6. Httpd服务入门知识-http协议版本,工作机制及http服务器应用扫盲篇

    Httpd服务入门知识-http协议版本,工作机制及http服务器应用扫盲篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Internet与中国 Internet最早来源于美 ...

  7. docker中使用阿里云的apt源安装各种实用工具

    今天想在docker中安装vim工具,还有其他的软件等等,如果你直接执行apt-get install vim是没有用的,会显示: root@7d43d83fd3a8:/etc/nginx# apt- ...

  8. Django bootstrap按钮点击后激活active

    现在有个需求,就是在导航栏上有若干个按钮,我想实现的功能是当点击某个按钮后修改文字颜色,这样网站会更人性化.现总结方法如下: index.html: <ul class="navbar ...

  9. PHP数组操作类

    class ArrayHelper{           /**      * 从数组中删除空白的元素(包括只有空白字符的元素)      *      * 用法:      * @code php ...

  10. CustomHTTPProtocol

    http://blog.csdn.net/jingcheng345413/article/details/54967739 一.概念 NSURLProtocol也是苹果众多黑魔法中的一种,使用它可以轻 ...