基于devops利用微服务引入三方服务----测试准备

1.部署流程说明

记录了本地测试、上传代码到仓库,主要是为了完整的手动操作一遍,同时熟悉一下如何使用vscode来构建spring boot工程,具体过程是

1、vscode构建了两个spring boot工程
2、初始化工程获取本地maven库
3、上传本地库到maven私有库,同时配置快照库和发布库相关配置
4、手动单节点部署容器应用
5、手动部署容器应用到swarm集群

2.本地配置spring boot项目

因为要引入nacos实现服务注册与发现,需要写两个项目,一个注册服务,一个发现服务

2.1.注册服务

创建项目
vscode->ctrl+shift+p
07spring1

07spring2

07spring3

07spring13

07spring5

07spring6

删除demo文件,修改provider目录为controller,并创建相关代码

生成的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.8.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.teng</groupId>
	<artifactId>provider</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba.cloud</groupId>
			<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>com.alibaba.cloud</groupId>
				<artifactId>spring-cloud-alibaba-dependencies</artifactId>
				<version>${spring-cloud-alibaba.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

创建HelloWorldController.java

package com.teng.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class HelloWorldController {

    @GetMapping("/hello/{name}")
    public String hello(@PathVariable String name) {
        return "Hello " + name + " , Welcome to Nacos Discovery!!!";
    }
}

创建ProviderController.java

package com.teng;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;


@EnableDiscoveryClient
@SpringBootApplication
public class ProviderApplication {

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

application.properties中配置nacos

server.port=8081
spring.application.name=nacos-discovery-provider

spring.cloud.nacos.discovery.server-addr=192.168.0.151:8848

spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos

management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

最终的目录结构
07spring14

2.2.发现服务

创建项目
vscode->ctrl+shift+p
07spring1

07spring2

07spring3

07spring7

07spring5

07spring6

07spring9

将上图中的consumer修改为controller,并删除demo文件
生成的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.8.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.teng</groupId>
	<artifactId>consumer</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba.cloud</groupId>
			<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>com.alibaba.cloud</groupId>
				<artifactId>spring-cloud-alibaba-dependencies</artifactId>
				<version>${spring-cloud-alibaba.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

创建文件TestController.java

package com.teng.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;


@RestController
public class TestController {

    @Autowired
    LoadBalancerClient loadBalancerClient;

    @GetMapping("/test")
    public String test() {
        // 通过spring cloud common中的负载均衡接口选取服务提供节点实现接口调用
        ServiceInstance serviceInstance = loadBalancerClient.choose("nacos-discovery-provider");
        String url = serviceInstance.getUri() + "/hello/" + "xiaoliang";
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.getForObject(url, String.class);
    }
}

创建ConsumerApplication.java

package com.teng;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {

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

application.properties中配置nacos


server.port=8082
spring.application.name=nacos-discovery-consumer

spring.cloud.nacos.discovery.server-addr=192.168.0.151:8848

spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos


management.endpoints.web.exposure.include=*

最终的目录结构
07spring10

启动工程
07spring11

访问工程
http://localhost:8082/test

查看nacos
访问http://192.168.0.151:8848/nacos
07spring12

ps:启动工程有两种方式,直接F5开始调试或者根目录执行mvn clean install package生成jar包后执行java -jar 包名

3.上传maven本地库到私有库

3.1.获取本地库

开发人员本地首次mvn的时候肯定是从远端去下载依赖包,一般需要修改为国内的源这样构建会快一点
更换maven源为阿里云源,在maven的settings.xml里添加如下设置

    <mirror>
      <id>alimaven</id>
      <name>aliyun maven</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>        
    </mirror>

pom.xml里添加配置

	<repositories>
		<repository>
			<id>alimaven</id>
			<name>aliyun maven</name>
			<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
			<releases>
				<enabled>true</enabled>
			</releases>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>

maven在打包时下载的包默认缓存在如下位置
07mvn1

也可以自定义缓存空间,maven配置文件settings.xml里设置

<localRepository>D:/maven_repository</localRepository>

3.2.创建私有库

访问http://192.168.0.152:8081

07mvn3

将其加入maven-public
07mvn4

3.3.上传本地库到私有库

构建完后,把本地缓存的所有库文件上传至可以连通nexus私服的主机上,创建一个目录比如repo,同时在该机器上安装maven、jdk,这些过程具体不细述,安装后根据前面部署的maven私服来给项目和maven添加一些配置
在maven全局配置settings中在如下地方添加

  <mirror>
      <id>maven-public</id>
      <mirrorOf>*</mirrorOf>
      <name>maven-public</name>
      <url>http://192.168.0.152:8081/repository/maven-public/</url>
    </mirror>

添加认证

<server>
        <id>maven-public</id>
        <username>waka2020</username>
        <password>!QAZ1qaz</password>
    </server>
<server>
        <id>maven-releases</id>
        <username>waka2020</username>
        <password>!QAZ1qaz</password>
    </server>
<server>
        <id>maven-snapshots</id>
        <username>waka2020</username>
        <password>!QAZ1qaz</password>
    </server>

pom.xml添加配置

 <!-- 设置deploy的地址 -->
    <distributionManagement>
        
        <repository>
            <id>maven-releases</id>                    <!--库的ID-->
            <name>maven-releases</name>   <!--库的名字-->
            <url>http://192.168.0.152:8081/repository/maven-releases/</url>
        </repository>

        <snapshotRepository>
            <id>maven-snapshots</id>
            <name>maven-snapshot</name>
            <url>http://192.168.0.152:8081/repository/maven-snapshots/</url>
        </snapshotRepository>

    </distributionManagement>

在maven全局配置settings.xml里设置三个仓库(public releases sanpshots)的授权账号,同时设置私服地址为maven-public的地址,pom.xml里添加releases、snapshots仓库的地址,用于将本地的依赖包deploy到对应的仓库(maven-release、maven-sanpshots),注意deploy的包是通过mvn install命令下载缓存的jar包,不是package生成的jar包

进入repo,执行下面的导入脚本
cat import.sh

#!/bin/bash
# copy and run this script to the root of the repository directory containing files
# this script attempts to exclude uploading itself explicitly so the script name is important
# Get command line params
while getopts ":r:u:p:" opt; do
        case $opt in
                r) REPO_URL="$OPTARG"
                ;;
                u) USERNAME="$OPTARG"
                ;;
                p) PASSWORD="$OPTARG"
                ;;
        esac
done

find . -type f -not -path './mavenimport\.sh*' -not -path '*/\.*' -not -path '*/\^archetype\-catalog\.xml*' -not -path '*/\^maven\-metadata\-local*\.xml' -not -path '*/\^maven\-metadata\-deployment*\.xml' | sed "s|^\./||" | xargs -I '{}' curl -u "$USERNAME:$PASSWORD" -X PUT -v -T {} ${REPO_URL}/{} ;

执行脚本
bash import.sh -u waka2020 -r http://192.168.0.152:8081/repository/maven-local/ -p !QAZ1qaz

查看maven-local
07mvn5

查看maven-public
07mvn6

3.4.发布自建工程到私有库

工程根目录执行
mvn deploy
其部署过程在下载包的时候按照的顺序是先从本地仓库下载,本地仓库没有就去私有库下载,私有库没有就去中央仓库下载,中央仓库下载后会缓存到私有库,最后可以在对应的snapshots库或releases库
找到上传的工程
07mvn7

4.发布应用

4.1.构建专用打包镜像

drwxr-xr-x.  6 root  root         99 Jul  6 14:31 apache-maven-3.5.4
-rw-r--r--.  1 root  root    8842660 Jul  6 14:29 apache-maven-3.5.4-bin.tar.gz
drwxr-xr-x.  7 root  root        226 Jul  8 12:53 consumer
-rw-r--r--.  1 root  root        970 Jul  8 11:15 Dockerfile
drwxr-xr-x.  7 10143 10143       245 Mar 12 14:37 jdk1.8.0_251
-rw-r--r--.  1 root  root  195132576 Jul  6 14:29 jdk-8u251-linux-x64.tar.gz
drwxr-xr-x. 20 root  root       4096 Jul  7 12:24 maven-local
drwxr-xr-x. 20 root  root       4096 Jul  7 16:47 maven_repository
-rw-r--r--.  1 root  root  117326527 Jul  7 02:25 maven_repository.zip
drwxr-xr-x.  6 root  root        191 Jul  8 12:42 provider
-rw-r--r--.  1 root  root   35140274 Jul  6 16:32 provider.zip
-rw-r--r--.  1 root  root      10854 Jul  8 11:09 settings.xml

cat Dockerfile

FROM centos:7
MAINTAINER linuxwt <tengwanginit@gmail.com>

######更换163源######
RUN yum -y install wget \
gcc \
&& wget http://mirrors.163.com/.help/CentOS7-Base-163.repo \
&& mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak \
&& mv -f CentOS7-Base-163.repo /etc/yum.repos.d/CentOS-Base.repo \
&& yum makecache

######配置jdk#####
WORKDIR /usr
RUN mkdir /usr/local/java
ADD jdk-8u251-linux-x64.tar.gz /usr/local/java
RUN ln -s /usr/local/java/jdk1.8.0_251 /usr/local/java/jdk 
ENV JAVA_HOME /usr/local/java/jdk 
ENV JRE_HOME ${JAVA_HOME}/jre 
ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib 
ENV PATH ${JAVA_HOME}/bin:$PATH 

###配置maven###### 
WORKDIR /usr
RUN mkdir /usr/local/maven
ADD apache-maven-3.5.4-bin.tar.gz /usr/local/maven
RUN ln -s /usr/local/maven/apache-maven-3.5.4 /usr/local/maven/maven
ADD settings.xml /usr/local/maven/maven/conf/settings.xml
ENV MAVEN_HOME /usr/local/maven/maven
ENV PATH ${MAVEN_HOME}/bin:$PATH

该镜像配置了maven私有仓库、jdk、maven
docker build -t soa-maven-jdk:v1 .
上传到docker私有仓库
docker tag soa-maven-jdk:v1 192.168.0.152:8082/soa-maven-jdk:v1

4.2.手动部署应用

同样是以服务注册和服务提供这两个工程为例

注册服务

total 12
-rw-r--r--. 1 root root  574 Jul  8 12:42 docker-compose.yml
-rw-r--r--. 1 root root  262 Jul  8 12:11 Dockerfile
-rw-r--r--. 1 root root 3065 Jul  7 16:28 pom.xml
drwxr-xr-x. 4 root root   30 Jul  5 13:47 src
drwxr-xr-x. 9 root root  241 Jul  7 16:47 target

构建应用镜像
cat Dockerfile

FROM 192.168.0.152:8082/soa-maven-jdk:v1  as build-stage
WORKDIR /usr/local/project 
COPY . .
RUN mvn clean package
#####
FROM 192.168.0.152:8082/soa-maven-jdk:v1 
WORKDIR /tmp
ENV TZ=Asia/Shanghai
COPY --from=build-stage /usr/local/project/target .
CMD ["java","-jar","provider-0.0.1-SNAPSHOT.jar"]

docker build -t provider:v1 .

cat docker-compose.yml

version: "3.4"
services:
  provider:
    image: provider:v1
    networks:
      - service_overlay
      - monitor_overlay
      - database_overlay
      - elk_overlay
    ports:
      - 8083:8083
    volumes:
      -  "/etc/localtime:/etc/localtime:ro"
    deploy:
      placement:
        constraints: [node.hostname==node150]
      restart_policy:
        condition: any
        delay: 5s
        max_attempts: 3
networks:
  service_overlay:
    external: true
  monitor_overlay:
    external: true
  database_overlay:
    external: true
  elk_overlay:
    external: true

启动服务
docker stack deploy -c docker-compose.yml 150

发现服务

[root@node150 consumer]# ll
total 12
-rw-r--r--. 1 root root  593 Jul  8 15:24 docker-compose.yml
-rw-r--r--. 1 root root  299 Jul  8 15:20 Dockerfile
-rw-r--r--. 1 root root 2530 Jul  5 23:50 pom.xml
drwxr-xr-x. 4 root root   30 Jul  5 23:50 src
drwxr-xr-x. 9 root root  241 Jul  7 02:33 target

构建应用镜像
cat Dockerfile

FROM 192.168.0.152:8082/soa-maven-jdk:v1  as build-stage
WORKDIR /usr/local/project 
COPY . .
RUN mvn clean package
#####
FROM 192.168.0.152:8082/soa-maven-jdk:v1
WORKDIR /tmp
ENV TZ=Asia/Shanghai
COPY --from=build-stage /usr/local/project/target .
CMD ["java","-jar","consumer-0.0.1-SNAPSHOT.jar"]

docker build -t consumer:v1 .

cat docker-compose.yml

version: "3.4"
services:
  consumer:
    image: consumer:v1
    networks:
      - service_overlay
      - monitor_overlay
      - database_overlay
      - elk_overlay
    ports:
      - 8084:8084
    volumes:
      -  "/etc/localtime:/etc/localtime:ro"
    deploy:
      placement:
        constraints: [node.hostname==node151]
      restart_policy:
        condition: any
        delay: 5s
        max_attempts: 3
networks:
  service_overlay:
    external: true
  monitor_overlay:
    external: true
  database_overlay:
    external: true
  elk_overlay:
    external: true

启动服务前目标节点上需要部署用到的镜像
docker save consumer:v1 -o consumer.tar
scp consumer.tar 192.168.0.151:/root
远程至151节点
docker load -i consumer.tar
docker tag 上载的镜像的ID consumer:v1

启动服务
docker stack deploy -c docker-compose.yml 151
访问服务
http://192.168.0.151:8084/test