SpringBoot(十五):SpringBoot2.x集成eureka實現注高可用冊中心,高可用的服務器提供者,以及消費者示例

本文代碼請參考《https://github.com/478632418/springcloud-eureka-server-client/tree/master/mall》、《https://github.com/478632418/springboot-eurekahtml

本章節主要包含SpringCloud終端服務器註冊中心、服務提供者、服務器消費幾個角色的項目建立示例。java

咱們這裏選取Euerka做爲服務註冊發現框架,實際上能提供服務註冊與發現的框架並不止它一個,可是業界內使用這個還比較普遍,可是有人說它從2.0以後Netflix就不在維護它了,可是依然有很多公司還堅持選了它,由於它到2.0就已經很穩定了。git

Eureka註冊中心簡介

Eureka是Netflix開發的服務發現框架,自己是一個基於REST的服務,主要用於定位運行在AWS域中的中間層服務,以達到負載均衡和中間層服務故障轉移的目的。SpringCloud將它集成在其子項目spring-cloud-netflix中,以實現SpringCloud的服務發現功能。github

 

Eureka包含兩個組件:Eureka Server和Eureka Client。web

Eureka Server:提供服務註冊服務,服務啓動後,服務會在Eureka Server中進行註冊,包括主機與端口號、服務版本號、通訊協議等。這樣Eureka Server中的服務註冊表中將會存儲全部可用的服務節點的信息,服務節點的信息能夠在界面中直觀的看到。spring

Eureka Server端支持集羣模式部署,首尾相連造成一個閉環便可,集羣中的不一樣服務註冊中心經過異步模式互相複製各自的狀態,這也意味着在給定的時間點每一個實例中存儲的全部服務的狀態可能存在不一致的現象。docker

Eureka Client:主要處理服務的註冊和發現。客戶端服務經過註冊和參數配置的方式,嵌入在客戶端應用程序的代碼中。在應用程序啓動時,Eureka客戶端向服務註冊中心註冊自身提供的服務,並週期性的發送心跳來更新它的服務租約。同時,它也能從服務端查詢當前註冊的服務信息並把它們緩存到本地並週期性的刷新服務狀態。express

服務調用:apache

服務消費者在獲取服務清單後,經過服務名能夠獲取具體提供服務的實例名和該實例的元數據信息。由於有這些服務實例的詳細信息,因此客戶端能夠根據本身的需求決定具體調用哪一個實例,在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---壞~牧羊人

相關文章
相關標籤/搜索