Jenkins 微服务持续集成十四(Spring Cloud 微服务架构优化一:高可用生产部署服务器)

94 篇文章 9 订阅
7 篇文章 2 订阅
本文介绍了如何优化Jenkins+Docker+SpringCloud的部署方案,实现多微服务同时发布、多服务器集群部署,并详细阐述了优化后的部署流程,包括新增Docker服务器、修改微服务配置、设计Jenkins构建参数、构建测试以及最终的多服务器远程发布。通过这些步骤,提高了系统的可用性和容错率。
摘要由CSDN通过智能技术生成


Jenkins 微服务持续集成十(Spring Cloud 微服务一)
Jenkins 微服务持续集成十一(Spring Cloud 微服务二)
Jenkins 微服务持续集成十二(Spring Cloud 微服务三)
Jenkins 微服务持续集成十三(Spring Cloud 微服务四)


一、Jenkins + Docker + SpringCloud 部署方案优化

上面部署方案存在的问题:

  • 一次只能选择一个微服务部署
  • 只有一台生产部署服务器
  • 每个微服务只有一个实例,容错率低

优化方案:

  • 在一个 Jenkins 工程中可以选择多个微服务同时发布
  • 在一个 Jenkins 工程中可以选择多台生产服务器同时部署
  • 每个微服务都是以集群高可用形式部署

二、Jenkins + Docker + SpringCloud 集群部署流程说明

在这里插入图片描述

服务器名称IP 地址安装的软件
代码托管服务器192.168.10.20Gitlab
持续集成服务器192.168.10.30Jenkins,Maven,Git,JDK,Sonarqube,Docker20.10.12-ce
Docker 仓库服务器192.168.10.40JDK,Tomcat,Docker20.10.12-ceHarbor1.9.2
生产部署服务器一192.168.10.50Docker20.10.12-ce
生产部署服务器二192.168.10.115Docker20.10.12-ce

三、新增一台 Docker 服务器

参考:
安装 Docker

指向 harbor 地址

[root@c7-5 ~]#vim /etc/docker/daemon.json 

{
  "registry-mirrors": ["https://4iv7219l.mirror.aliyuncs.com"],
  "insecure-registries": ["192.168.10.40:85"]
}

[root@c7-5 ~]#systemctl restart docker

四、修改所有微服务配置

修改各个模块的 application.yml 的 eureka 生产服务器地址为集群模式,我们新增了一个地址。

1. eureka

# 集群版
spring:
  application:
    name: EUREKA-HA


---
server:
  port: 10086
spring:
  # 指定profile=eureka-server1
  profiles: eureka-server1
eureka:
  instance:
    # 指定当profile=eureka-server1时,主机名是eureka-server1
    hostname: 192.168.10.50
  client:
    service-url:
      # 将自己注册到eureka-server1、eureka-server2这个Eureka上面去
      defaultZone: http://192.168.10.50:10086/eureka/,http://192.168.10.115:10086/eureka/

---
server:
  port: 10086
spring:
  profiles: eureka-server2
eureka:
  instance:
    hostname: 192.168.10.115
  client:
    service-url:
      defaultZone: http://192.168.10.50:10086/eureka/,http://192.168.10.115:10086/eureka/

2. zuul

server:
  port: 10020 # 端口
  
# 基本服务信息
spring:
  application:
    name: tensquare-zuul # 服务ID
    
# Eureka配置
eureka:
  client:
    service-url:  
      defaultZone: http://192.168.10.50:10086/eureka,http://192.168.10.115:10086/eureka # Eureka访问地址
  instance:
    prefer-ip-address: true
  
# 修改ribbon的超时时间
ribbon:
  ConnectTimeout: 1500 # 连接超时时间,默认500ms
  ReadTimeout: 3000  # 请求超时时间,默认1000ms
  
  
# 修改hystrix的熔断超时时间
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMillisecond: 2000 # 熔断超时时长,默认1000ms
            

# 网关路由配置
zuul:
  routes:
    admin:
      path: /admin/**
      serviceId: tensquare-admin-service
    gathering:
          path: /gathering/**
          serviceId: tensquare-gathering

 # jwt参数
jwt:
  config:
    key: itcast
    ttl: 1800000

3. admin

server: 
  port: 9001
spring: 
  application:  
    name: tensquare-admin-service #指定服务名
  datasource:  
    driverClassName: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.10.30:3306/tensquare_user?characterEncoding=UTF8
    username: root
    password: 123456
  jpa: 
    database: mysql
    show-sql: true

#Eureka配置
eureka:
  client:
    service-url:
      defaultZone: http://192.168.10.50:10086/eureka,http://192.168.10.115:10086/eureka
  instance:
    lease-renewal-interval-in-seconds: 5 # 每隔5秒发送一次心跳
    lease-expiration-duration-in-seconds: 10 # 10秒不发送就过期
    prefer-ip-address: true


 # jwt参数
jwt:
  config:
    key: itcast
    ttl: 1800000

4. gathering

server: 
  port: 9002
spring: 
  application:  
    name: tensquare-gathering #指定服务名
  datasource:  
    driverClassName: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.10.30:3306/tensquare_gathering?characterEncoding=UTF8
    username: root
    password: 123456
  jpa: 
    database: mysql
    show-sql: true
#Eureka客户端配置
eureka:
  client:
    service-url:
      defaultZone: http://192.168.10.50:10086/eureka,http://192.168.10.115:10086/eureka
  instance:
    lease-renewal-interval-in-seconds: 5 # 每隔5秒发送一次心跳
    lease-expiration-duration-in-seconds: 10 # 10秒不发送就过期
    prefer-ip-address: true

5. 提交微服务代码

在这里插入图片描述


五、设计 Jenkins 集群项目的构建参数

1. 安装 Extended Choice Parameter 插件支持多选框

在这里插入图片描述

2. 创建流水线项目

在这里插入图片描述

3. 添加参数

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

添加两个参数
字符串参数:分支名称
在这里插入图片描述
在这里插入图片描述

多选框:项目名称
在这里插入图片描述
在这里插入图片描述

tensquare_eureka_server@10086,tensquare_zuul@10020,tensquare_admin_service@9001,tensquare_gathering@9002

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

查看构建界面效果
在这里插入图片描述


六、构建测试

1. 检查代码循环构建

1.1 修改 jenkinsfile

//git 的凭证
def git_auth="0b127895-eb97-4f8f-b471-1277e5549b54"
//git 的 URL
def git_url="git@192.168.10.20:test-group/tensquare_back.git"
//镜像标签
def tag="latest"
//harbor的url地址
def harbor_url="192.168.10.40:85"
//镜像仓库名
def harbor_name="tensquare"
//harbor的凭证
def harbor_auth="9269e103-c017-4555-bdf0-d9d8b56bc889"

node {

    //获取当前选择项目名称
    def selectedProjectNames="${project_name}".split(",")

    stage('pull code') {
        //切换成变量,字符串符号使用双引号
        checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
    }
    stage('check code') {
        for(int i=0;i<selectedProjectNames.length;i++){
            //项目信息  tensquare_eureka_server@10086
            def projectInfo=selectedProjectNames[i]

            //当前的项目名称
            def currentProjectName="${projectInfo}".split("@")[0]

            //当前的项目端口
            def currentProjectPort="${projectInfo}".split("@")[1]

            //定义SonarQubeScanner工具
            def scannerHome = tool 'sonar-scanner'
                //引用SonarQube系统环境
                withSonarQubeEnv('sonarqube') {
                sh """
                    cd ${currentProjectName}
                    ${scannerHome}/bin/sonar-scanner
                   """
                }
        }
    }
    //添加公共子工程
    stage('make install public sub project') {
            sh "mvn -f tensquare_common clean install"
    }
    //打包微服务,制作镜像
    stage('make package') {
        sh "mvn -f ${project_name} clean package dockerfile:build"
        //定义镜像名称
        def imageName="${project_name}:${tag}"
        //对镜像打标签
        sh "docker tag ${imageName} ${harbor_url}/${harbor_name}/${imageName}"
        //镜像推送到harbor
        withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
            //登录harbor
            sh "docker login -u ${username} -p ${password} ${harbor_url}"
            //镜像上传
            sh "docker push ${harbor_url}/${harbor_name}/${imageName}"
            sh "echo 镜像上传成功"
            //部署应用
            sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh ${harbor_url} ${harbor_name} ${project_name} ${tag} ${port}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
        }
    }
}

提交 jenkinsfile
在这里插入图片描述

1.2 构建测试

我们选择两个服务构建,看看是否执行了两次代码审查,最后肯定构建失败(打 jar 包还有配置需要修改)。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 循环打包编译制作镜像

2.1 修改 jenkinsfile

//git 的凭证
def git_auth="0b127895-eb97-4f8f-b471-1277e5549b54"
//git 的 URL
def git_url="git@192.168.10.20:test-group/tensquare_back.git"
//镜像标签
def tag="latest"
//harbor的url地址
def harbor_url="192.168.10.40:85"
//镜像仓库名
def harbor_name="tensquare"
//harbor的凭证
def harbor_auth="9269e103-c017-4555-bdf0-d9d8b56bc889"

node {

    //获取当前选择项目名称
    def selectedProjectNames="${project_name}".split(",")

    stage('pull code') {
        //切换成变量,字符串符号使用双引号
        checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
    }
    stage('check code') {
        for(int i=0;i<selectedProjectNames.length;i++){
            //项目信息  tensquare_eureka_server@10086
            def projectInfo=selectedProjectNames[i]

            //当前的项目名称
            def currentProjectName="${projectInfo}".split("@")[0]

            //当前的项目端口
            def currentProjectPort="${projectInfo}".split("@")[1]

            //定义SonarQubeScanner工具
            def scannerHome = tool 'sonar-scanner'
                //引用SonarQube系统环境
                withSonarQubeEnv('sonarqube') {
                sh """
                    cd ${currentProjectName}
                    ${scannerHome}/bin/sonar-scanner
                   """
                }
        }
    }
    //添加公共子工程
    stage('make install public sub project') {
            sh "mvn -f tensquare_common clean install"
    }
    //打包微服务,制作镜像
    stage('make package images,push images') {
        for(int i=0;i<selectedProjectNames.length;i++){
            //项目信息  tensquare_eureka_server@10086
            def projectInfo=selectedProjectNames[i]

            //当前的项目名称
            def currentProjectName="${projectInfo}".split("@")[0]

            //当前的项目端口
            def currentProjectPort="${projectInfo}".split("@")[1]

            sh "mvn -f ${currentProjectName} clean package dockerfile:build"
            //定义镜像名称
            def imageName="${currentProjectName}:${tag}"
            //对镜像打标签
            sh "docker tag ${imageName} ${harbor_url}/${harbor_name}/${imageName}"
            //镜像推送到harbor
            withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
                //登录harbor
                sh "docker login -u ${username} -p ${password} ${harbor_url}"
                //镜像上传
                sh "docker push ${harbor_url}/${harbor_name}/${imageName}"
                sh "echo 镜像上传成功"
            }
        }
                //部署应用
        sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh ${harbor_url} ${harbor_name} ${project_name} ${tag} ${port}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
    }
}

提交 jenkinsfile
在这里插入图片描述

2.2 构建测试

最后还是会报错,发布步骤还没改。
在这里插入图片描述
在这里插入图片描述

七、完成微服务多服务器远程发布

1. 配置远程部署服务器

从 Jenkins 服务器拷贝公钥到 docker2 远程服务器

ssh-copy-id 192.168.10.115

在这里插入图片描述

系统配置 -》添加远程服务器
在这里插入图片描述

2. 修改 Docker 配置信任 Harbor 私服地址

在这里插入图片描述
重启 Docker

3. 添加参数

tensquare_back_cluster 项目,先前的参数不要删了

多选框:部署服务器
在这里插入图片描述
在这里插入图片描述

页面效果
在这里插入图片描述

4. 修改 Jenkinsfile 构建脚本

//git 的凭证
def git_auth="0b127895-eb97-4f8f-b471-1277e5549b54"
//git 的 URL
def git_url="git@192.168.10.20:test-group/tensquare_back.git"
//镜像标签
def tag="latest"
//harbor的url地址
def harbor_url="192.168.10.40:85"
//镜像仓库名
def harbor_name="tensquare"
//harbor的凭证
def harbor_auth="9269e103-c017-4555-bdf0-d9d8b56bc889"

node {

    //获取当前选择项目名称
    def selectedProjectNames="${project_name}".split(",")
    //获取当前选择服务器
    def selectedServers="${publish_server}".split(",")

    stage('pull code') {
        //切换成变量,字符串符号使用双引号
        checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
    }
    stage('check code') {
        for(int i=0;i<selectedProjectNames.length;i++){
            //项目信息  tensquare_eureka_server@10086
            def projectInfo=selectedProjectNames[i]

            //当前的项目名称
            def currentProjectName="${projectInfo}".split("@")[0]

            //当前的项目端口
            def currentProjectPort="${projectInfo}".split("@")[1]

            //定义SonarQubeScanner工具
            def scannerHome = tool 'sonar-scanner'
                //引用SonarQube系统环境
                withSonarQubeEnv('sonarqube') {
                sh """
                    cd ${currentProjectName}
                    ${scannerHome}/bin/sonar-scanner
                   """
                }
        }
    }
    //添加公共子工程
    stage('make install public sub project') {
            sh "mvn -f tensquare_common clean install"
    }
    //打包微服务,制作镜像
    stage('make package images,push images') {
        for(int i=0;i<selectedProjectNames.length;i++){
            //项目信息  tensquare_eureka_server@10086
            def projectInfo=selectedProjectNames[i]

            //当前的项目名称
            def currentProjectName="${projectInfo}".split("@")[0]

            //当前的项目端口
            def currentProjectPort="${projectInfo}".split("@")[1]

            sh "mvn -f ${currentProjectName} clean package dockerfile:build"
            //定义镜像名称
            def imageName="${currentProjectName}:${tag}"
            //对镜像打标签
            sh "docker tag ${imageName} ${harbor_url}/${harbor_name}/${imageName}"
            //镜像推送到harbor
            withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
                //登录harbor
                sh "docker login -u ${username} -p ${password} ${harbor_url}"
                //镜像上传
                sh "docker push ${harbor_url}/${harbor_name}/${imageName}"
                sh "echo 镜像上传成功"
            }

            //遍历所有服务器,分别部署
            for (int j=0;j<selectedServers.length;j++){
                //获取当前服务器名称
                def currentServerName=selectedServers[j]
                //调用不同服务器模块内容--spring.profiles.active=eureka-server1/eureka-server2
                def activeProfile="--spring.profiles.active="

                //根据不同的服务器名称调用不同的服务器配置信息
                if (currentServerName=="master_server"){
                    activeProfile=activeProfile+"eureka-server1"
                }else if (currentServerName=="slave_server"){
                    activeProfile=activeProfile+"eureka-server2"
                }
                //部署应用
                sshPublisher(publishers: [sshPublisherDesc(configName: "${currentServerName}", transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deployCluster.sh ${harbor_url} ${harbor_name} ${currentProjectName} ${tag} ${currentProjectPort} ${activeProfile}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
            }
        }
    }
}

上传到 gitlab
在这里插入图片描述

5. 编写 deployCluster.sh 部署脚本

放到两台生产服务器中路径:/opt/jenkins_shell/deployCluster.sh

脚本内容(注意修改用户密码)

#! /bin/sh
#接收外部参数
harbor_url=$1
harbor_project_name=$2
project_name=$3
tag=$4
port=$5
profile=$6

imageName=$harbor_url/$harbor_project_name/$project_name:$tag

echo "$imageName"

#查询容器是否存在,存在则删除
containerId=`docker ps -a | grep -w ${project_name}:${tag}  | awk '{print $1}'`

if [ "$containerId" !=  "" ] ; then
    #停掉容器
    docker stop $containerId

    #删除容器
    docker rm $containerId
 
 echo "成功删除容器"
fi

#查询镜像是否存在,存在则删除
imageId=`docker images | grep -w $project_name  | awk '{print $3}'`

if [ "$imageId" !=  "" ] ; then
      
    #删除镜像
    docker rmi -f $imageId
 
 echo "成功删除镜像"
fi


# 登录Harbor
docker login -u tom -p Zc120604 $harbor_url

# 下载镜像
docker pull $imageName

# 启动容器
docker run -di -p $port:$port $imageName $profile

echo "容器启动成功"

记得授权

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

6. 构建测试

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

将其他服务构建
在这里插入图片描述
在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值