五、Jenkins、Docker、SpringClound持续集成

Jenkins、Docker、SpringClound持续集成

  • 一、部署介绍
    • 1.部署图
    • 2.微服务项目结构
    • 3.项目启动顺序
  • 二、微服务项目在Windows运行
    • 1.配置java、maven环境
    • 2.初始化数据库表/数据
      • 2.1 tensquare_gathering服务表
      • 2.2 tensquare_gathering服务表
    • 3.启动微服务
    • 4.微服务接口测试
      • 4.1 获取用户token
      • 4.2 获取所有活动
  • 三、本地打包和运行微服务
    • 1.安装SpringBoot打包库
    • 2.打包微服务
    • 3.本地运行jar包
    • 4.打包遇到的坑
  • 四、打包前端代码
  • 五、使用Dockerfile制作微服务镜像
    • 1.Dockerfile常见命令
    • 2.编写eureka服务Dockerfile
      • 2.1 将jar包上传linux
      • 2.2 编写Dockerfile
      • 2.3 构建镜像
      • 2.4 启动容器
      • 2.5 访问容器
  • 六、Docker部署Harbor
    • 1.安装
    • 2.访问
    • 3.创建项目
    • 4.创建用户
    • 5.给用户分配项目
    • 6.本地镜像上传
      • 6.1 给镜像打上标签
      • 6.2 将harbor地址添加到Docker白名单
      • 6.3 命令行登录harbor
      • 6.4 推送镜像
      • 6.5 从Harbor下载镜像
        • 6.5.1 命令行登录Harbor
        • 6.5.2 拉取镜像
  • 七、微服务持续集成-案例
    • 1.项目上传到gitlab
      • 1.1 创建git项目
      • 1.2 IDEA上传后端项目
        • 1.2.1 配置git程序
        • 1.2.2 配置GitLab
        • 1.2.3 上传代码
      • 1.3 Git上传前端代码
    • 2.在Jenkins从GitLab拉取源码
      • 2.1 创建Jenkins微服务项目
        • 2.1.1 创建后端Jenkins项目
        • 2.1.2 编写Jenkins脚本文件
        • 2.1.3 编写每个微服务harbor配置
          • 2.1.3.1 zuul
          • 2.1.3.2 eureka
          • 2.1.3.3 admin_service
          • 2.1.3.3 gathering
        • 2.1.4 流水线添加harbor
    • 3.微服务打包
      • 3.1 Jenkins环境准备
        • 3.1.1 安装项目java环境
        • 3.1.2 安装maven环境
        • 3.1.3 将父工程依赖文件放入maven环境
        • 3.1.4 docker环境
      • 3.2 对公共子工程打包
      • 3.3 对微服务打包
    • 4.使用Dockerfile编译、生成镜像
      • 4.1 配置构建docker的插件
      • 4.2 配置Dockerfile
    • 5.上传到Harbor镜像库
    • 6.拉取镜像和发布应用
      • 6.1 Jenkins安装发布插件
      • 6.2 ssh公钥配置
        • 6.2.1 公钥传输
        • 6.2.2 jenkins公钥配置
        • 6.2.2 jenkins项目构建添加端口参数
        • 6.2.3 Jenkinsfile添加部署命令
        • 6.2.3 编写sh部署脚本
      • 6.3 导入微服务的表和数据
      • 6.4 修改所有微服务注册中心配置地址
      • 6.4 按顺序构建docker并自动部署
      • 6.5 测试接口
    • 7.部署前端静态web网站
      • 7.1 部署服务器安装nginx
      • 7.2 Jenkins配置NodeJS
        • 7.2.1 安装NodeJS插件
        • 7.2.2 安装NodeJS版本
      • 7.3 创建前端流水线
      • 7.4 修改前端文件BASE_API地址
      • 7.5 Jenkins构建
  • 八、微服务持续集成-优化
    • 1.存在的问题
    • 2.集群版eureka配置
      • 2.1 eureka微服务配置文件
      • 2.2 其他微服务配置文件
      • 2.3 Jenkins多选类型参数
        • 2.3.1 安装多选框组件
        • 2.3.2 创建流水线项目
        • 2.3.3 添加微服务项目多选参数
        • 2.3.4 添加部署服务器多选参数
      • 2.4 Jenkinsfile编写
      • 2.5 部署sh脚本编写
  • 八、Nginx+zuul集群实现高可用网关
    • 1.安装nginx
    • 2.修改nginx配置
    • 3.重启nginx

一、部署介绍

1.部署图

2.微服务项目结构

  1. tensquare_admin_service:权限认证服务(登录、注销、token分发等)
  2. tensquare_common:工具类
  3. tensquare_eureka_server:单机版eureka服务
  4. tensquare_gathering:业务服务
  5. tensquare_zuul:zuul网关服务

3.项目启动顺序

  1. tensquare_eureka_server
  2. tensquare_zuul
  3. tensquare_admin_service
  4. tensquare_gathering

二、微服务项目在Windows运行

1.配置java、maven环境

  • IDEA配置java、maven环境
  • 配置好环境后,使用maven下载好所有的依赖包

2.初始化数据库表/数据

2.1 tensquare_gathering服务表

/*
SQLyog 企业版 - MySQL GUI v8.14 
MySQL - 5.7.4-m14 : Database - tensquare_gathering
*********************************************************************
*//*!40101 SET NAMES utf8 */;/*!40101 SET SQL_MODE=''*/;/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`tensquare_gathering` /*!40100 DEFAULT CHARACTER SET utf8 */;USE `tensquare_gathering`;/*Table structure for table `tb_city` */DROP TABLE IF EXISTS `tb_city`;CREATE TABLE `tb_city` (`id` varchar(20) NOT NULL COMMENT 'ID',`name` varchar(20) DEFAULT NULL COMMENT '城市名称',`ishot` varchar(1) DEFAULT NULL COMMENT '是否热门',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='城市';/*Data for the table `tb_city` */insert  into `tb_city`(`id`,`name`,`ishot`) values ('1','北京','1'),('2','上海','1'),('3','广州','1'),('4','深圳','1'),('5','天津','0'),('6','重庆','0'),('7','西安','0');/*Table structure for table `tb_gathering` */DROP TABLE IF EXISTS `tb_gathering`;CREATE TABLE `tb_gathering` (`id` varchar(20) NOT NULL COMMENT '编号',`name` varchar(100) DEFAULT NULL COMMENT '活动名称',`summary` text COMMENT '大会简介',`detail` text COMMENT '详细说明',`sponsor` varchar(100) DEFAULT NULL COMMENT '主办方',`image` varchar(100) DEFAULT NULL COMMENT '活动图片',`starttime` date DEFAULT NULL COMMENT '开始时间',`endtime` date DEFAULT NULL COMMENT '截止时间',`address` varchar(100) DEFAULT NULL COMMENT '举办地点',`enrolltime` datetime DEFAULT NULL COMMENT '报名截止',`state` varchar(1) DEFAULT NULL COMMENT '是否可见',`city` varchar(20) DEFAULT NULL COMMENT '城市',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='活动';/*Data for the table `tb_gathering` */insert  into `tb_gathering`(`id`,`name`,`summary`,`detail`,`sponsor`,`image`,`starttime`,`endtime`,`address`,`enrolltime`,`state`,`city`) values ('1','测试活动6666','喝茶看电影,不亦乐乎','喝茶看电影,不亦乐乎','黑马程序员',NULL,'2019-11-01','2019-11-01','广州市黑马程序员',NULL,'1','6'),('94377594140','aaaa',NULL,NULL,NULL,NULL,'2019-11-01','2019-11-01',NULL,NULL,'1','1'),('943776146707845','aaaa',NULL,NULL,'ssss',NULL,'2019-11-01','2019-11-01','cccc',NULL,'1','1'),('943776663576121344','aaaa',NULL,NULL,NULL,NULL,'2019-11-01','2019-11-01',NULL,NULL,'1','2'),('943783521749700608','2342423',NULL,NULL,'23454534',NULL,'2019-11-01','2019-11-01','545435435',NULL,'1','2'),('944085821768732672','JAVAEE茶话会',NULL,NULL,'传智',NULL,'2019-11-01','2019-11-01','金燕龙',NULL,'1','2'),('944086086991351808','是',NULL,NULL,'11',NULL,'2019-11-01','2019-11-01','11',NULL,'1','3'),('944090372710207488','大讨论',NULL,NULL,'小马',NULL,'2019-11-01','2019-11-01','消息',NULL,'1','3'),('944105652622594048','测试测试',NULL,NULL,'测试者',NULL,'2019-11-01','2019-11-01','测试地址',NULL,'1','4'),('945227340642914304','111',NULL,NULL,'222',NULL,'2019-11-01','2019-11-01','333',NULL,'1','5'),('945227678527655936','111',NULL,NULL,'222',NULL,'2019-11-01','2019-11-01','333',NULL,'1','5'),('945235087564345344','啊啊',NULL,NULL,'1',NULL,'2019-11-01','2019-11-01','1',NULL,'1','1'),('945235534329024512','1',NULL,NULL,'1',NULL,'2019-11-01','2019-11-01','1',NULL,'1','2'),('945235859786043392','1',NULL,NULL,'1',NULL,'2019-11-01','2019-11-01','1',NULL,'1','3');
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

2.2 tensquare_gathering服务表

/*
SQLyog 企业版 - MySQL GUI v8.14 
MySQL - 5.7.4-m14 : Database - tensquare_user
*********************************************************************
*//*!40101 SET NAMES utf8 */;/*!40101 SET SQL_MODE=''*/;/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`tensquare_user` /*!40100 DEFAULT CHARACTER SET utf8 */;USE `tensquare_user`;/*Table structure for table `tb_admin` */DROP TABLE IF EXISTS `tb_admin`;CREATE TABLE `tb_admin` (`id` varchar(20) NOT NULL COMMENT 'ID',`loginname` varchar(100) DEFAULT NULL COMMENT '登陆名称',`password` varchar(100) DEFAULT NULL COMMENT '密码',`state` varchar(1) DEFAULT NULL COMMENT '状态',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='管理员';/*Data for the table `tb_admin` */insert  into `tb_admin`(`id`,`loginname`,`password`,`state`) values ('1194281533230419968','admin','$2a$10$PhnLmwA7QarH8M/Wc52Mfekoyqw74Vp619M2p2dnxq0Ltz6xXTWJu','1');/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

3.启动微服务

按顺序执行以下服务的Application文件:
tensquare_eureka_server
tensquare_zuul
tensquare_admin_service
tensquare_gathering
在这里插入图片描述

  • 查看注册中心
    在这里插入图片描述

4.微服务接口测试

4.1 获取用户token

  • Method:POST
  • URL:http://localhost:10020/admin/admin/login
  • Payload:
{"loginname": "admin", "password": "123456"}
  • Response:
{"flag": true,"code": 20000,"message": "管理员登录成功","data": {"roles": "admin","name": "admin","id": "1194281533230419968","token": "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMTk0MjgxNTMzMjMwNDE5OTY4Iiwic3ViIjoiYWRtaW4iLCJpYXQiOjE3MTIzOTg5NDQsInJvbGVzIjoiYWRtaW4iLCJleHAiOjE3MTI0MDA3NDR9.59JOUrd8E4YlEZwZL3n-nxyOIL620cT2YqjA61N1sRg"}
}

4.2 获取所有活动

  • Method:GET
  • URL:http://localhost:10020/gathering/gathering
  • Header
token:eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMTk0MjgxNTMzMjMwNDE5OTY4Iiwic3ViIjoiYWRtaW4iLCJpYXQiOjE3MTIzOTg5NDQsInJvbGVzIjoiYWRtaW4iLCJleHAiOjE3MTI0MDA3NDR9.59JOUrd8E4YlEZwZL3n-nxyOIL620cT2YqjA61N1sRg

在这里插入图片描述

三、本地打包和运行微服务

1.安装SpringBoot打包库

  • 如果不使用下面的插件,那么打包的jar包是不包含依赖包。
  • 在父工程下的pom.xml写入下面的库
    <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>

在这里插入图片描述

2.打包微服务

如果用的IDEA 2020,那么maven需要用3.6.3,否则会报错

  • 总共有四个微服务,最终打包后有4个jar包
  • 四个微服务都是如下图的操作
    在这里插入图片描述

3.本地运行jar包

  • jar -r xxx.jar

4.打包遇到的坑

  • 在没有主文件的工程,在pom.xml需要加入以下
    <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><executable>true</executable></configuration><executions><execution><phase>none</phase></execution></executions></plugin></plugins></build>

四、打包前端代码

  • 技术栈:NodeJS+VueJS+ElementUI
# 1.本地运行
npm run dev
# 2.打包静态web网站
npm run build
# 打包后,产生dist目录的静态文件
# 3.部署到nginx服务器把dist目录的静态文件拷贝到nginx的html目录,启动nginx

五、使用Dockerfile制作微服务镜像

1.Dockerfile常见命令

命令作用
FROM image_name:tag
MAINTAINER user_name声明镜像的作者
ENV key value设置环境变量 (可以写多条)
RUN command编译镜像时运行的脚本(可以写多条)
CMD设置容器的启动命令
ENTRYPOINT设置容器的入口程序
ADD source_dir/file dest_dir/file将宿主机的文件复制到容器内,如果是一个压缩文件,将会在复制后自动解压
COPY source_dir/file dest_dir/file和ADD相似,但是如果有压缩文件并不能解压
WORKDIR path_dir设置工作目录
ARG设置编译镜像时加入的参数
VOLUMN设置容器的挂载卷
  • RUN、CMD、ENTRYPOINT的区别?
    • RUN:用于指定 docker build 过程中要运行的命令,即是创建 Docker 镜像(image)的步骤
    • CMD:设置容器的启动命令, Dockerfile 中只能有一条 CMD 命令,如果写了多条则 后一条生效,CMD不支持接收docker run的参数。
    • ENTRYPOINT:入口程序是容器启动时执行的程序, docker run 中 后的命令将作为参数传递给入口程序 ,ENTRYPOINY类似于 CMD 指令,但可以接收docker run的参数 。

2.编写eureka服务Dockerfile

  • 其他服务和eureka服务的镜像构建步骤是一样的。

2.1 将jar包上传linux

2.2 编写Dockerfile

FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 10086
ENTRYPOINT ["java", "-jar", "/app.jar"]
  • 参数解析:
    • FROM openjdk:8-jdk-alpine:拉取openjdk:8-jdk-alpine作为基础镜像
    • ARG JAR_FILE:定义一个JAR_FILE参数,需要外部传入
    • COPY ${JAR_FILE} app.jar:拷贝一个文件,命名为app.jar
    • EXPOSE 10086:暴露10086端口
    • EXTRYPOINT ["java", "-jar", "/app.jar"]:设置java项目启动命令

2.3 构建镜像

docker build --build-arg JAR_FILE=tensquare_eureka_server-1.0-SNAPSHOT.jar -t eureka:v1 .

在这里插入图片描述

2.4 启动容器

docker run -i --name=eureka -p 10086:10086 eureka:v1

2.5 访问容器

  • http://192.168.86.128:10086

六、Docker部署Harbor

1.安装

  • Harbor是基于docker的,所以需要安装docker和docker-compose。
  • docker和docker-compose版本要求:
    • docker 20.10.10-ce+
    • docker-compose 1.18.0+
  • 注意事项:
    • 数据存放路径应在配置文件中配置到一个容量比较充足的共享存储中
    • Harbor是使用docker-compose命令来管理的,如果需要停止Harbor也应用docker-compose stop来停止
  • 部署docker教程:https://blog.csdn.net/qq_37344058/article/details/131270071
  • 部署docker-compose教程:https://blog.csdn.net/qq_37344058/article/details/136065167
  • 下载地址:https://github.com/goharbor/harbor/releases
    • 需要下载offline的压缩包
      在这里插入图片描述
# 1.下载harbor安装包
wget https://github.com/goharbor/harbor/releases/download/v2.9.3/harbor-offline-installer-v2.9.3.tgz# 2.解压到/usr/local,并进入到解压目录
tar zxvf harbor-offline-installer-v2.9.3.tgz -C /usr/local/ && cd /usr/local/harbor/# 3.拷贝一份配置文件
cp harbor.yml.tmpl harbor.yml# 4.查看当前主机全称
hostname# 5.修改配置文件
vi harbor.yml
# 5.1 修改hostname
# 5.2 https这行及子行都注释掉,因为没有弄ssl证书加密
  • 下面hostname尽量填IP地址,填hostname有问题
    在这里插入图片描述
# 6.启动harbor
./install.sh

在这里插入图片描述
注意:这是因为在启动docker的时候防火墙做了策略,如果容器在运行中,停止防火墙,在操作容器就会报这个错误,我们可以重启docker解决此问题
重启docker服务:systemctl restart docker.service
启动harbor:docker-compose up -d

  • Harbor的命令汇总
    • 启动harbor:docker-compose up -d
    • 关闭harbor:docker-compose stop
    • 重启harbor:docker-compose restart

2.访问

访问地址:harbor的服务器ip地址
账号密码:用户名(admin)、密码(可在harbor.yml配置文件中找到,修改密码的话也在这里面改)

3.创建项目

  • Harbor的项目分为公开和私有的
    • 公开项目:所有用户都可以访问,通常存放公共的镜像,默认有一个library公开项目。
    • 私有项目:只有授权用户才可以访问,通常存放项目本身的镜像。
  • 以下为微服务创建一个项目
    在这里插入图片描述
    在这里插入图片描述
  • 创建了个私有项目

4.创建用户

在这里插入图片描述

5.给用户分配项目

  • 分配项目的时候,可以选择角色:
    • 项目管理员:对当前项目有所有权限
    • 维护人员:拥有对 Harbor 系统的维护权限,包括监控系统状态、执行备份和恢复操作、维护存储等。
    • 开发人员:对镜像进行上传和下载
    • 访客:只能下载,不能上传
      在这里插入图片描述

6.本地镜像上传

  • 上传刚刚创建的eureka镜像

6.1 给镜像打上标签

# 通用格式:docker tag 镜像名称:镜像版本 harbor的IP:85/项目名称/镜像名称:镜像版本
docker tag eureka:v1 192.168.86.128/tensquare/eureka:v1

6.2 将harbor地址添加到Docker白名单

  • 默认情况,docker不允许把镜像传入到harbor,因为docker不新人harbor地址

vi /etc/docker/daemon.json

{"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"],"insecure-registries": ["192.168.86.128"]
}

重启docker:systemctl restart docker
启动harbor:cd /usr/local/harbor && docker-compose up -d

6.3 命令行登录harbor

docker login -u 用户名 -p 密码 192.168.86.128

6.4 推送镜像

docker push 192.168.86.128/tensquare/eureka:v1

在这里插入图片描述

6.5 从Harbor下载镜像

6.5.1 命令行登录Harbor
docker login -u 用户名 -p 密码 192.168.86.128
6.5.2 拉取镜像
docker pull 192.168.86.128/tensquare/eureka:v1

七、微服务持续集成-案例

1.项目上传到gitlab

1.1 创建git项目

  • 需要创建两个项目:
    • 前端:tensquare_front
    • 后端:tensquare_back
      在这里插入图片描述

1.2 IDEA上传后端项目

1.2.1 配置git程序

在这里插入图片描述

1.2.2 配置GitLab

在这里插入图片描述

  • 将ssh的链接,填入进去即可。
1.2.3 上传代码

在这里插入图片描述
在这里插入图片描述

1.3 Git上传前端代码

  • 步骤
    • 将前端仓库clone
    • 将前端代码粘贴进去
    • 提交后push
# 1.将前端仓库clone
git clone ssh://git@192.168.86.128:9922/tensquare/tensquare_front.git
cd tensquare_front
# 2.创建分支
git switch --create main
# 3.提交代码
git add . && git commit -m "初始化项目" && git push --set-upstream origin main

在这里插入图片描述

2.在Jenkins从GitLab拉取源码

2.1 创建Jenkins微服务项目

  • 创建两个微服务项目,并且都是流水线项目
    • 前端:tensquare_front
    • 后端:tensquare_back
2.1.1 创建后端Jenkins项目

在这里插入图片描述
在这里插入图片描述

2.1.2 编写Jenkins脚本文件
  • 脚本文件放到父工程根根目录:Jenkinsfile
  • 下面是脚本式
  • 检出git脚本生成
    在这里插入图片描述
checkout scmGit(branches: [[name: '*/master']], extensions: [], userRemoteConfigs: [[credentialsId: '6856b58c-2349-4673-aec6-278f08335aff', url: 'http://192.168.86.128:9980/tensquare/tensquare_back.git']])
  • 将一些变量抽取出来
//git凭证ID
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"
//git的url地址
def git_url = "http://192.168.86.128:9980/tensquare/tensquare_back.git"node {stage('拉取代码') {checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}
}

在这里插入图片描述

2.1.3 编写每个微服务harbor配置
  • 在每一个微服务下面,防止一个harbor代码扫描的配置文件:sonar-project.properties
2.1.3.1 zuul
# must be unique in a given SonarQube instance
sonar.projectKey=tensquare_zuul
# this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1.
sonar.projectName=tensquare_zuul
sonar.projectVersion=1.0# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
# This property is optional if sonar.modules is set.
sonar.sources=.
sonar.exclusions=**/test/**,**/target/**
sonar.java.binaries=.sonar.java.source=1.8
sonar.java.target=1.8
#sonar.java.libraries=**/target/classes/**# Encoding of the source code. Default is default system encoding
sonar.sourceEncoding=UTF-8
2.1.3.2 eureka
# must be unique in a given SonarQube instance
sonar.projectKey=tensquare_eureka_server
# this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1.
sonar.projectName=tensquare_eureka_server
sonar.projectVersion=1.0# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
# This property is optional if sonar.modules is set.
sonar.sources=.
sonar.exclusions=**/test/**,**/target/**
sonar.java.binaries=.sonar.java.source=1.8
sonar.java.target=1.8
#sonar.java.libraries=**/target/classes/**# Encoding of the source code. Default is default system encoding
sonar.sourceEncoding=UTF-8
2.1.3.3 admin_service
# must be unique in a given SonarQube instance
sonar.projectKey=tensquare_admin_service
# this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1.
sonar.projectName=tensquare_admin_service
sonar.projectVersion=1.0# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
# This property is optional if sonar.modules is set.
sonar.sources=.
sonar.exclusions=**/test/**,**/target/**
sonar.java.binaries=.sonar.java.source=1.8
sonar.java.target=1.8
#sonar.java.libraries=**/target/classes/**# Encoding of the source code. Default is default system encoding
sonar.sourceEncoding=UTF-8
2.1.3.3 gathering
# must be unique in a given SonarQube instance
sonar.projectKey=tensquare_gathering
# this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1.
sonar.projectName=tensquare_gathering
sonar.projectVersion=1.0# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
# This property is optional if sonar.modules is set.
sonar.sources=.
sonar.exclusions=**/test/**,**/target/**
sonar.java.binaries=.sonar.java.source=1.8
sonar.java.target=1.8
#sonar.java.libraries=**/target/classes/**# Encoding of the source code. Default is default system encoding
sonar.sourceEncoding=UTF-8
2.1.4 流水线添加harbor
  • 由于涉及到多个微服务,构建的时候,需要有个下拉框可以选择,构建哪些微服务。以下是添加微服务名称下拉框,可以多选
    在这里插入图片描述
  • 下面是加入了代码扫描的pipeline代码
//git凭证ID
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"
//git的url地址
def git_url = "http://192.168.86.128:9980/tensquare/tensquare_back.git"node {stage('拉取代码') {checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}stage('代码审查') {//定义当前Jenkins的SonarQubeScanner工具:下面配置的是 全局配置里面的namedef scannerHome = tool 'sonar-scanner'//引用当前JenkinsSonarQube环境:下面配置的是系统配置的namewithSonarQubeEnv('SonarQube-Server') {sh """cd ${project_name}${scannerHome}/bin/sonar-scanner"""}}
}

3.微服务打包

3.1 Jenkins环境准备

3.1.1 安装项目java环境
3.1.2 安装maven环境
  • 安装教程:https://qingsi.blog.csdn.net/article/details/137710489
  • maven环境如果安装了,运行jenkins报错
    在这里插入图片描述
  • 因为Jenkins 通过shell脚本调用 mvn 命令的时候,是从/usr/bin 文件夹中找命令的
ln -s /usr/local/maven/apache-maven-3.6.3/bin/mvn /usr/bin/mvn
ln -s /usr/local/maven/apache-maven-3.6.3/bin/mvn /usr/local/bin/mvn
3.1.3 将父工程依赖文件放入maven环境
  • 第一种方案:资料包里面有:tensquare_parent.tar.gz
    • 放入到:/data/mavenfile/com/tensquare下面
  • 第二种方案:打包安装父工程:mvn -f pom.xml clean install
    • pom.xml是父工程的
3.1.4 docker环境
  • 需要安装docker环境

3.2 对公共子工程打包

  • 由于公共子工程不是Spring服务启动的,而其他的服务依赖于这个包,所以需要提前将公共子工程打包好,并且安装到maven本地仓库
  • 在Jenkinsfile加入打包子工程打包安装的步骤
//git凭证ID
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"
//git的url地址
def git_url = "http://192.168.86.128:9980/tensquare/tensquare_back.git"node {stage('拉取代码') {checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}stage('代码审查') {//定义当前Jenkins的SonarQubeScanner工具:下面配置的是 全局配置里面的namedef scannerHome = tool 'sonar-scanner'//引用当前JenkinsSonarQube环境:下面配置的是系统配置的namewithSonarQubeEnv('SonarQube-Server') {sh """cd ${project_name}${scannerHome}/bin/sonar-scanner"""}}stage('编译,安装公共子工程') {sh "mvn -f tensquare_common clean install"}
}

3.3 对微服务打包

  • 在Jenkinsfile加入新步骤打包微服务
//git凭证ID
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"
//git的url地址
def git_url = "http://192.168.86.128:9980/tensquare/tensquare_back.git"node {stage('拉取代码') {checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}stage('代码审查') {//定义当前Jenkins的SonarQubeScanner工具:下面配置的是 全局配置里面的namedef scannerHome = tool 'sonar-scanner'//引用当前JenkinsSonarQube环境:下面配置的是系统配置的namewithSonarQubeEnv('SonarQube-Server') {sh """cd ${project_name}${scannerHome}/bin/sonar-scanner"""}}stage('编译,安装公共子工程') {sh "mvn -f tensquare_common clean install"}stage('编译,打包微服务工程') {sh "mvn -f ${project_name} clean package"}
}

4.使用Dockerfile编译、生成镜像

4.1 配置构建docker的插件

  • 在每个微服务项目的pom.xml加入dockerfile-maven-plugin插件
<plugin><groupId>com.spotify</groupId><artifactId>dockerfile-maven-plugin</artifactId><version>1.3.6</version><configuration><repository>${project.artifactId}</repository><buildArgs><JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE></buildArgs></configuration>
</plugin>

4.2 配置Dockerfile

  • 在每个微服务项目根目录下建立Dockerfile文件
  • 注意:每个项目公开的端口不一样
#FROM java:8
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 9002
ENTRYPOINT ["java","-jar","/app.jar"]
  • 在父工程的Jenkinsfile添加docker build的命令
//git凭证ID
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"
//git的url地址
def git_url = "http://192.168.86.128:9980/tensquare/tensquare_back.git"node {stage('拉取代码') {checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}stage('代码审查') {//定义当前Jenkins的SonarQubeScanner工具:下面配置的是 全局配置里面的namedef scannerHome = tool 'sonar-scanner'//引用当前JenkinsSonarQube环境:下面配置的是系统配置的namewithSonarQubeEnv('SonarQube-Server') {sh """cd ${project_name}${scannerHome}/bin/sonar-scanner"""}}stage('编译,安装公共子工程') {sh "mvn -f tensquare_common clean install"}stage('编译,打包微服务工程') {sh "mvn -f ${project_name} clean package dockerfile:build"}
}

在这里插入图片描述

5.上传到Harbor镜像库

  • 修改Jenkinsfile脚本
//git凭证ID
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"
//git的url地址
def git_url = "http://192.168.86.128:9980/tensquare/tensquare_back.git"
//镜像的版本号
def tag = "latest"
//Harbor的url地址
def harbor_url = "192.168.86.128"
//镜像库项目名称
def harbor_project = "tensquare"
//Harbor的登录凭证ID:这个ID,是在jenkins里面创建的凭证(harbor的账号密码)的ID
def harbor_auth = "bf8ca22e-aee0-4533-bf63-185dac0bef1a"node {stage('拉取代码') {checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}stage('代码审查') {//定义当前Jenkins的SonarQubeScanner工具:下面配置的是 全局配置里面的namedef scannerHome = tool 'sonar-scanner'//引用当前JenkinsSonarQube环境:下面配置的是系统配置的namewithSonarQubeEnv('SonarQube-Server') {sh """cd ${project_name}${scannerHome}/bin/sonar-scanner"""}}stage('编译,安装公共子工程') {sh "mvn -f tensquare_common clean install"}stage('编译,打包微服务工程,上传镜像') {sh "mvn -f ${project_name} clean package dockerfile:build"//定义镜像名称def imageName = "${project_name}:${tag}"//对镜像打上标签sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"//把镜像推送到HarborwithCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {//登录到Harborsh "docker login -u ${username} -p ${password} ${harbor_url}"//镜像上传sh "docker push ${harbor_url}/${harbor_project}/${imageName}"sh "echo 镜像上传成功"}}
}
  • jenkins打包发布成功
    在这里插入图片描述
  • harbor显示有镜像保存
    在这里插入图片描述

6.拉取镜像和发布应用

  • 本次案例,在jenkins的服务器(192.168.86.128)上面,发布到应用服务器(192.168.86.131)上面部署。和部署到其他服务器一样的步骤。
  • 部署应用的机器环境:
    • 确保安装了docker

6.1 Jenkins安装发布插件

  • Publish Over SSH插件
    在这里插入图片描述

6.2 ssh公钥配置

6.2.1 公钥传输
  • 查看jenkins的机器上是否有密钥公钥:
    • 查看/root/.ssh 是否有:id_rsa.pub、id_rsa文件
      在这里插入图片描述
  • 如果没有的话,需要生成:
ssh-keygen -t rsa -C 'xxx@xxx.com'
# 下面一路回车即可
  • 将jenkins服务器的公钥,传送到应用部署的服务器上
ssh-copy-id 192.168.86.128

在这里插入图片描述

6.2.2 jenkins公钥配置

在这里插入图片描述

  • Passphrase:是填写jenkins服务器生成的ssh key的密码,一般置空,不予理睬
  • path to key:jenkins服务器生成的私钥存放目录文件。
  • key:直接填写jenkins服务器生成的私钥。
  • 注意:path to key 和 key 二选一即可
6.2.2 jenkins项目构建添加端口参数
  • 这个参数用于传入到启动微服务容器的端口
    在这里插入图片描述
    在这里插入图片描述
6.2.3 Jenkinsfile添加部署命令
  • 可以在流水线代码生成那里生成命令
    在这里插入图片描述
//git凭证ID
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"
//git的url地址
def git_url = "http://192.168.86.128:9980/tensquare/tensquare_back.git"
//镜像的版本号
def tag = "latest"
//Harbor的url地址
def harbor_url = "192.168.86.128"
//镜像库项目名称
def harbor_project = "tensquare"
//Harbor的登录凭证ID:这个ID,是在jenkins里面创建的凭证(harbor的账号密码)的ID
def harbor_auth = "bf8ca22e-aee0-4533-bf63-185dac0bef1a"node {stage('拉取代码') {checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}stage('代码审查') {//定义当前Jenkins的SonarQubeScanner工具:下面配置的是 全局配置里面的namedef scannerHome = tool 'sonar-scanner'//引用当前JenkinsSonarQube环境:下面配置的是系统配置的namewithSonarQubeEnv('SonarQube-Server') {sh """cd ${project_name}${scannerHome}/bin/sonar-scanner"""}}stage('编译,安装公共子工程') {sh "mvn -f tensquare_common clean install"}stage('编译,打包微服务工程,上传镜像') {sh "mvn -f ${project_name} clean package dockerfile:build"//定义镜像名称def imageName = "${project_name}:${tag}"//对镜像打上标签sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"//把镜像推送到HarborwithCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {//登录到Harborsh "docker login -u ${username} -p ${password} ${harbor_url}"//镜像上传sh "docker push ${harbor_url}/${harbor_project}/${imageName}"def i = "docker push ${harbor_url}/${harbor_project}/${imageName}"sh "echo ${i}"sh "echo 镜像上传成功"}// 部署应用// 1.execCommand的$port,需要作为一个构建参数传入sh "echo 开始部署"def execCommand = "/opt/jenkins_shell/deploy.sh ${harbor_url} ${harbor_project} ${project_name} ${tag} ${port}"sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "${execCommand}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])sh "echo 部署完成"}
}
6.2.3 编写sh部署脚本
  • 该放置到部署应用服务器,路径为:/opt/jenkins_shell
  • 脚本名称:deploy.sh
  • 注意:脚本需要授权:chmod +x de
#! /bin/sh
#接收外部参数
harbor_url=$1
harbor_project_name=$2
project_name=$3
tag=$4
port=$5imageName=$harbor_url/$harbor_project_name/$project_name:$tagecho "$imageName"#查询容器是否存在,存在则删除
containerId=`docker ps -a | grep -w ${project_name}:${tag}  | awk '{print $1}'`
if [ "$containerId" !=  "" ] ; then#停掉容器docker stop $containerId#删除容器docker rm $containerIdecho "成功删除容器"
fi#查询镜像是否存在,存在则删除
imageId=`docker images | grep -w $project_name  | awk '{print $3}'`if [ "$imageId" !=  "" ] ; then#删除镜像docker rmi -f $imageIdecho "成功删除镜像"
fi# 登录Harbor
docker login -u admin -p Harbor12345 $harbor_url# 下载镜像
docker pull $imageName# 启动容器
docker run -di -p $port:$port $imageNameecho "容器启动成功"

6.3 导入微服务的表和数据

  • tensquare_gathering.sql、tensquare_user.sql

6.4 修改所有微服务注册中心配置地址

  • 将注册中心的地址,改为实际部署的服务器地址

6.4 按顺序构建docker并自动部署

  • 微服务构建顺序:
    • tensquare_eureka_server
    • tensquare_zuul
    • tensquare_admin_service
    • tensquare_gathering
      在这里插入图片描述

6.5 测试接口

  • 登录接口
    在这里插入图片描述

7.部署前端静态web网站

在这里插入图片描述

7.1 部署服务器安装nginx

  • Docker部署nginx教程:https://blog.csdn.net/qq_37344058/article/details/137742556

7.2 Jenkins配置NodeJS

7.2.1 安装NodeJS插件
  • 安装插件NodeJS
    在这里插入图片描述
7.2.2 安装NodeJS版本

在这里插入图片描述

7.3 创建前端流水线

  • 项目名称:tensquare_front
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
// gitlab的凭证
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"node {stage('拉取代码') {checkout scmGit(branches: [[name: '*/${branch}']], extensions: [], userRemoteConfigs: [[credentialsId: '${git_auth}', url: 'http://192.168.86.128:9980/tensquare/tensquare_front.git']])}stage('代码审查') {// 使用NodeJS的npm进行打包nodejs("nodejs12"){sh '''npm installnpm run build'''// 以下为远程调用进行项目部署:使用的是目录拷贝的方式sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '/root/docker/nginx/html', remoteDirectorySDF: false, removePrefix: 'dist', sourceFiles: 'dist/**')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])}}
}

7.4 修改前端文件BASE_API地址

  • 修改为网关地址
    在这里插入图片描述

7.5 Jenkins构建

在这里插入图片描述

八、微服务持续集成-优化

1.存在的问题

  • 上面部署方案存在的问题:
    • 一次只能选择一个微服务部署
    • 只有一台生产者部署服务器
    • 每个微服务只有一个实例,容错率低
  • 优化方案:
    • 在一个Jenkins工程中可以选择多个微服务同时发布
    • 在一个Jenkins工程中可以选择多台生产服务器同时部署
    • 每个微服务都是以集群高可用形式部署
      在这里插入图片描述

2.集群版eureka配置

2.1 eureka微服务配置文件

  • 在启动微服务的时候,加入参数: spring.profiles.active 来读取对应的配置
# 集群版
spring:application:name: EUREKA-HA---
server:port: 10086
spring:# 指定profile=eureka-server1profiles: eureka-server1
eureka:instance:# 指定当profile=eureka-server1时,主机名是eureka-server1hostname: 192.168.86.131client:service-url:# 将自己注册到eureka-server1、eureka-server2这个Eureka上面去defaultZone: http://192.168.86.131:10086/eureka/,http://192.168.86.132:10086/eureka/---
server:port: 10086
spring:profiles: eureka-server2
eureka:instance:hostname: 192.168.86.132client:service-url:defaultZone: http://192.168.86.131:10086/eureka/,http://192.168.86.132:10086/eureka/

2.2 其他微服务配置文件

  • 将defaultZone改为:http://192.168.86.131:10086/eureka/,http://192.168.86.132:10086/eureka
    在这里插入图片描述

2.3 Jenkins多选类型参数

2.3.1 安装多选框组件
  • Extended Choice Parameter Plugin
    在这里插入图片描述
2.3.2 创建流水线项目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.3.3 添加微服务项目多选参数

在这里插入图片描述
在这里插入图片描述

2.3.4 添加部署服务器多选参数

在这里插入图片描述

2.4 Jenkinsfile编写

//git凭证ID
def git_auth = "6856b58c-2349-4673-aec6-278f08335aff"
//git的url地址
def git_url = "http://192.168.86.128:9980/tensquare/tensquare_back.git"
//镜像的版本号
def tag = "latest"
//Harbor的url地址
def harbor_url = "192.168.86.128"
//镜像库项目名称
def harbor_project = "tensquare"
//Harbor的登录凭证ID:这个ID,是在jenkins里面创建的凭证(harbor的账号密码)的ID
def harbor_auth = "bf8ca22e-aee0-4533-bf63-185dac0bef1a"node {// 获取当前选择的项目名称def selectedProjectNames = "${project_name}".split(",")//获取当前选择的服务器名称def selectedServers = "${publish_server}".split(",")stage('拉取代码') {checkout scmGit(branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]])}stage('代码审查') {// for循环每个项目代码for(int i=0;i<selectedProjectNames.length;i++){// tensquare_eureka_server@10086def projectInfo = selectedProjectNames[i];// 当前遍历的项目名称def currentProjectName = "${projectInfo}".split("@")[0]// 当前遍历的项目端口def currentProjectPort = "${projectInfo}".split("@")[1]//定义当前Jenkins的SonarQubeScanner工具:下面配置的是 全局配置里面的namedef scannerHome = tool 'sonar-scanner'//引用当前JenkinsSonarQube环境:下面配置的是系统配置的namewithSonarQubeEnv('SonarQube-Server') {sh """cd ${currentProjectName}${scannerHome}/bin/sonar-scanner"""}}}stage('编译,安装公共子工程') {sh "mvn -f tensquare_common clean install"}stage('编译,打包微服务工程,上传镜像') {// for循环每个项目代码for(int i=0;i<selectedProjectNames.length;i++){// tensquare_eureka_server@10086def projectInfo = selectedProjectNames[i];// 当前遍历的项目名称def currentProjectName = "${projectInfo}".split("@")[0]// 当前遍历的项目端口def currentProjectPort = "${projectInfo}".split("@")[1]sh "mvn -f ${project_name} clean package dockerfile:build"//定义镜像名称def imageName = "${currentProjectName}:${tag}"//对镜像打上标签sh "docker tag ${imageName} ${harbor_url}/${harbor_project}/${imageName}"//把镜像推送到HarborwithCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {//登录到Harborsh "docker login -u ${username} -p ${password} ${harbor_url}"//镜像上传sh "docker push ${harbor_url}/${harbor_project}/${imageName}"def i = "docker push ${harbor_url}/${harbor_project}/${imageName}"sh "echo ${i}"sh "echo 镜像上传成功"}// 遍历所有的服务器,分别部署for(int j=0;j<selectedServers.length;j++){//获取当前遍历的服务器名称def currentServerName = selectedServers[j]//加上的参数格式:--spring.profiles.active=eureka-server1/eureka-server2def activeProfile = "--spring.profiles.active="//根据不同的服务名称来读取不同的Eureka配置信息if(currentServerName=="master_server"){activeProfile = activeProfile+"eureka-server1"}else if(currentServerName=="slave_server"){activeProfile = activeProfile+"eureka-server2"}// 部署应用def execCommand = "/opt/jenkins_shell/deployCluster.sh ${harbor_url} ${harbor_project} ${currentProjectName} ${tag} ${currentProjectPort} ${activeProfile}"sshPublisher(publishers: [sshPublisherDesc(configName: "${currentServerName}", transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "${execCommand}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])}}}
}

2.5 部署sh脚本编写

#! /bin/sh
#接收外部参数
harbor_url=$1
harbor_project_name=$2
project_name=$3
tag=$4
port=$5
profile=$6imageName=$harbor_url/$harbor_project_name/$project_name:$tagecho "$imageName"#查询容器是否存在,存在则删除
containerId=`docker ps -a | grep -w ${project_name}:${tag}  | awk '{print $1}'`if [ "$containerId" !=  "" ] ; then#停掉容器docker stop $containerId#删除容器docker rm $containerIdecho "成功删除容器"
fi#查询镜像是否存在,存在则删除
imageId=`docker images | grep -w $project_name  | awk '{print $3}'`if [ "$imageId" !=  "" ] ; then#删除镜像docker rmi -f $imageIdecho "成功删除镜像"
fi# 登录Harbor
docker login -u eric -p Eric123456 $harbor_url# 下载镜像
docker pull $imageName# 启动容器
docker run -di -p $port:$port $imageName $profileecho "容器启动成功"

八、Nginx+zuul集群实现高可用网关

  • 这里只需要使用nginx的负载均衡功能即可
    在这里插入图片描述

1.安装nginx

  • 之前已经安装过

2.修改nginx配置

vi /etc/nginx/nginx.conf

加入以下内容

    upstream zuulServer {server 192.168.66.103:10020 weight=1;server 192.168.66.104:10020 weight=1;}
server {location / {proxy_pass http://zuulServer/;}
}

3.重启nginx

  • 由于是docker部署的:docker restart nginx

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/816292.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

黑马苍穹外卖--再来一单(stream流转换、赋值与收集映射)

1.首先明确一下业务规则: 业务规则&#xff1a; 再来一单就是将原订单中的商品重新加入到购物车中 2.产品页面原型和开发接口文档 3.业务层逻辑代码开发 3.1 查询方向 我们要明确的是: 再来一单就是将原订单中的商品重新加入到购物车中------直接把商品加入到购物车&#…

prompt 工程整理(未完、持续更新)

工作期间会将阅读的论文、一些个人的理解整理到个人的文档中&#xff0c;久而久之就积累了不少“个人”能够看懂的脉络和提纲&#xff0c;于是近几日准备将这部分略显杂乱的内容重新进行梳理。论文部分以我个人的理解对其做了一些分类&#xff0c;并附上一些简短的理解&#xf…

分布式幂等性

1. 什么是幂等性&#xff1f; 幂等性是指在分布式系统中&#xff0c;一个操作多次执行的结果与其执行一次的结果相同。设计具有幂等性的分布式系统可以有效避免数据不一致和重复处理的问题。 幂等系统的应用场景 在微服务架构下&#xff0c;由于分布式天然特性的时序问题, 以…

【大语言模型】基础:TF-IDF

TF-IDF (Term Frequency-Inverse Document Frequency) 是一种用于信息检索与文本挖掘的统计方法&#xff0c;用来评估一个词对于一个文件集或一个语料库中的其中一份文件的重要性。它是一种常用于文本处理和自然语言处理的权重计算技术。 原理 TF-IDF 由两部分组成&#xff1…

二叉树例题分享

文章目录 二叉树例题分享[235. 二叉搜索树的最近公共祖先](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/)[701. 二叉搜索树中的插入操作](https://leetcode.cn/problems/insert-into-a-binary-search-tree/)[108. 将有序数组转换为二叉搜索树…

<计算机网络自顶向下> TCPUDP套接字编程

应用实现&#xff1a;源端的应用进程交换报文实现应用协议&#xff0c;来实现各种各样的网络应用&#xff08;dash&#xff0c;email, etc&#xff09; 而应用层通信不可以直接通信&#xff0c;需要借助下层的服务才可以进行&#xff0c;通过层间接口交给下层&#xff0c;通过…

基于java的社区生活超市管理系统

开发语言&#xff1a;Java 框架&#xff1a;ssm 技术&#xff1a;JSP JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclip…

CSS常用十大选择器(理论+代码实操)

HTML代码实例 注意&#xff1a;拷贝后本地运行注意head标签中的link标签的href属性是否正确 我的目录结构&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>Title</title><lin…

详解拷贝构造

拷贝构造的功能 写法&#xff1a; 拷贝构造函数的参数为什么是引用类型 系统自动生成的拷贝构造函数 拷贝构造的深拷贝与浅拷贝 概念 浅拷贝&#xff1a; 深拷贝 小结 拷贝构造的功能 拷贝构造函数可以把曾经实例化好的对象的数据拷贝给新创建的数据 &#xff0c;可见…

ASP.NET基于BS的计算机等级考试系统的设计与实现

摘 要 随着计算机技术的发展及计算机的日益普及&#xff0c;基于B/S结构的考试系统与无纸化办公一样已成为大势所趋。论文详细论述了一个基于B/S结构的计算机等级考试系统的设计过程。软件采用ASP.NET 2005作开发平台&#xff0c;C#作编程语言&#xff0c;SQL Server 2005作…

【DNS】

文章目录 DNS域名解析系统&#xff08;Domain Name System&#xff09;DNS系统需要解决的问题DNS域名解析系统&#xff08;Domain Name System&#xff09;问题1&#xff1a;DNS名字空间(The DNS Name Space&#xff09;DNS名字空间(The DNS Name Space)DNS名字空间(The DNS Na…

边缘计算【智能+安全检测】系列教程--使用OpenCV+GStreamer实现真正的硬解码,完全消除马赛克

通过现有博客的GST_URL = "rtspsrc location=rtsp://admin:abcd1234@192.168.1.64:554/h264/ch01/main/av_stream latency=150 ! rtph264depay ! avdec_h264 ! videorate ! videoconvert ! appsink sync=false" GStreamer的解码方式解码,大多情况应该存在上图马赛克…

解决jenkins运行sh报process apparently never started in XXX

个人记录 问题 process apparently never started in /var/jenkins_home/workspace/ks-springboot_mastertmp/durable-bbfe5f99(running Jenkins temporarily with -Dorg.jenkinsci.plugins.durabletask.BourneShellScript.LAUNCH_DIAGNOSTICStrue might make the problem cl…

架构师系列-搜索引擎ElasticSearch(八)- 集群管理故障恢复

故障转移 集群的master节点会监控集群中的节点状态&#xff0c;如果发现有节点宕机&#xff0c;会立即将宕机节点的分片数据迁移到其它节点&#xff0c;确保数据安全&#xff0c;这个叫做故障转移。 下图中node1是主节点&#xff0c;其他两个节点是从节点 节点故障 此时node1…

卷积神经网络(LeNet5实现对Fashion_MNIST分类

参考6.6. 卷积神经网络&#xff08;LeNet&#xff09; — 动手学深度学习 2.0.0 documentation (d2l.ai) ps&#xff1a;在这里预备使用pythorch 1.对 LeNet 的初步认识 总的来看&#xff0c;LeNet主要分为两个部分&#xff1a; 卷积编码器&#xff1a;由两个卷积层组成; …

OLTP 与 OLAP 系统说明对比和大数据经典架构 Lambda 和 Kappa 说明对比——解读大数据架构(五)

文章目录 前言OLTP 和 OLAPSMP 和 MPPlambda 架构Kappa 架构 前言 本文我们将研究不同类型的大数据架构设计&#xff0c;将讨论 OLTP 和 OLAP 的系统设计&#xff0c;以及有效处理数据的策略包括 SMP 和 MPP 等概念。然后我们将了解经典的 Lambda 架构和 Kappa 架构。 OLTP …

振兴国腾GM8775C MIPIDSI桥接到双 PORT LVDS

GM8775C描述&#xff1a; GM8775C 型 DSI 转双通道 LVDS 发送器产品主要实现将 MIPI DSI 转单 / 双通道 LVDS 功能&#xff0c;MIPI 支持 1/2/3/4 通道可选&#xff0c;每通道最高支持 1Gbps 速率&#xff0c;最大支持 4Gbps 速率。LVDS 时钟频率高达 154MHz &a…

Vue列表渲染

一、Vue列表渲染 1.用 v-for 把一个数组对应为一组元素 我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法&#xff0c;其中 items 是源数据数组&#xff0c;而 item 则是被迭代的数组元素的别名。 <ul id"exampl…

Facebook广告投放数据API对接流程

说明&#xff1a;仅供学习使用&#xff0c;请勿用于非法用途&#xff0c;若有侵权&#xff0c;请联系博主删除 作者&#xff1a;zhu6201976 一、需求背景 App在Facebook、Google等巨头进行广告投放&#xff0c;想要拿到实时广告投放效果数据&#xff0c;如曝光、点击、花费、触…

Django第三方功能的使用

Django第三方功能的使用 Django REST framework前言1、Django--Restframework--coreapi版文档BUG:AssertionError: coreapi must be installed for schema support.How to run Django with Uvicorn webserver?2、序列化类 Serializer的使用模型序列化类 ModelSerializer的使用…