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


    本文代码请参考《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.0
          build.artifactId: $project.artifactId$
          build.version: $project.version$
    #取消Ribbon使用Eureka
    #ribbon:
    #   eureka:
    #      enabled: true
    #配置Ribbon能访问 的微服务节点,多个节点用逗号隔开
    #spring-cloud-consumer:
    #    ribbon:
    #       listOfServers: localhost:8001,localhost:8002
    
    ---
    spring:
       profiles: slave1
    server:
       port: 6761
    management: 
      port: 54001
      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.0
        networks:
          - mall-server-net
        ports:
          - 6761:6761
        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---坏~牧羊人

  • 相关阅读:
    大一上的总结和大一下学期的目标
    [转]使用c# 模拟网站登录
    RegisterStartupScript和RegisterClientScriptBlock的区别
    关于PHP header函数跳转的问题
    asp.net 动态二维数组
    生成xml
    我们应该明确几个问题
    asp+ajax asp中ajax的中文乱码
    asp.net操作XML
    PHP Header用于页面跳转要注意的几个问题总结
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/11556891.html
Copyright © 2020-2023  润新知