相关文章推荐
幸福的红酒  ·  Install NPM and ...·  1 月前    · 
有腹肌的板栗  ·  使用 React 自带的 ...·  1 年前    · 
瘦瘦的人字拖  ·  Http处理 - ...·  2 年前    · 

一、架构

工作需要自己搭建维护一个Nexus集群,设计读高可用Nexus集群架构,参考[1]得到版本1架构设计如图1,版本2架构设计如图2,最终选用版本2架构设计,具体原因见“1.2、解决的问题及存在的问题”。

1.1、架构描述

1.1.1、版本1

设计有3个Nexus节点A,B,C,由于Nexus支持冷拷贝,因此通过冷拷贝进行A,B,C三个Nexus节点之间的同步,作者具体采用“rsync同步机制”作为同步实现。
节点A作为写入节点,Jenkins持续构建得到的包或者手动提交的包被写入到A,定时通过“rsync同步机制”保持B,C节点与A节点的同步,B,C节点作为读取节点,Maven客户端从B,C节点读取包数据。
为了获得读高可用,负载均衡和IP访问控制,在B,C节点与Maven客户端之间嵌入一个Nginx层。

1.1.2、版本2

设计有3个Nexus节点A,B,C,Jenkins持续构建得到的包或者手动提交的包写入时,重复写3份分别到A,B,C,读取A,B,C节点上包数据时通过Nginx反向代理,获得读高可用,负载均衡和IP访问控制。

1.2、解决的问题及存在的问题

1.2.1、版本1

以上架构设计解决问题如下:

  • 读取高可用
  • 数据丢失风险小
  • 以上架构设计存在问题如下:

  • Jenkins存在单点故障风险
  • 写节点存在单点故障风险
  • Nginx存在单点故障风险
  • 虽然Nexus支持冷拷贝,但是冷拷贝后存在数据与Nexus进程内存数据不一致问题,导致不能实时同步,甚至导致不能正常运行,因此冷拷贝只适用于“冷拷贝,冷重启”场景,因此版本1架构设计存在致命缺陷
  • 1.2.2、版本2

    以上架构设计解决问题如下:

  • 读取高可用
  • 数据丢失风险小
  • 以上架构设计存在问题如下:

  • Jenkins存在单点故障风险
  • Nginx存在单点故障风险
  • 二、具体搭建

    2.1、搭建Jenkins

    在D上搭建Jenkins具体流程如下:

  • 从官网下载最新的WAR包
  • 执行 java -jar jenkins.war --httpPort={自定义端口} 命令运行Jenkins,使用“httpPort”选项配置自定义端口
  • 访问“D:9091”,首次登录需要进行初始化配置,选择安装推荐插件,“admin”管理员用户的默认密码在“~/.jenkins/secrets/initialAdminPassword”文件内
  • 可在“系统管理–>全局工具配置”下个性化配置JDK,Maven,Git等工具,否则使用默认配置
  • 新建一个持续构建任务示例如下:

  • 输入“任务名称”,选择“构建一个自由风格的软件项目”
  • 在“源码管理”分栏下填写源码地址
  • 在“构建触发器”分栏下选择构建触发逻辑类型,一般为“Poll SCM(定时查看源码是否有更新,如果有更新就进行一次构建)”,比如 H/10 * * * * 表示每隔10分钟查看源码是否有更新
  • 在“构建环境”分栏下选择“Delete workspace before build starts”,避免旧构建结果对新构建的影响
  • 在“构建”分栏下选择“Execute Shell”,输入构建命令,见构建命令示例1
  • 在“构建后操作”分栏下选择“Archive the artifacts”,填写待打包资源的路径,比如 target/*.jar
  • 构建命令示例1

    mvn deploy -Dmaven.test.skip=true -DaltDeploymentRepository=maven-releases::default::http://A:8081/repository/maven-releases/
    mvn deploy -Dmaven.test.skip=true -DaltDeploymentRepository=maven-releases::default::http://B:8081/repository/maven-releases/
    mvn deploy -Dmaven.test.skip=true -DaltDeploymentRepository=maven-releases::default::http://C:8081/repository/maven-releases/
    

    2.2、搭建Nexus

    具体选用Nexus OSS 3.6.0-02开源版本。

    2.2.1、A节点

    A节点具体搭建Nexus具体流程如下:

  • 修改“bin/nexus”执行脚本中的INSTALL4J_JAVA_HOME_OVERRIDE变量,将其值设为1.8以上JDK的路径,执行bin/nexus start开启Nexus服务
  • 开启的Nexus服务默认监听8081端口,通过A:8081进行访问,admin用户的默认密码为admin123
  • Nexus的仓库有3种类型:“hosted,proxy,group”。“hosted”类型的仓库存储私人包;“proxy”类型的仓库代理远端仓库;“group”类型的仓库是组仓库,它管理多个仓库,访问它相当于访问该组下的所有仓库。Nexus默认配置有4个仓库:“maven-public(group类型),maven-releases(hosted类型),maven-snapshots(hosted类型),maven-central(proxy类型)”。“maven-central”默认代理官方Maven仓库(URL地址为:https://repo1.maven.org/maven2/),该代理仓库会缓存所代理的官方Maven仓库中的包,这样虽然会加快包获取速度,但是同时会大大增加硬盘占用大小,如果不需要可删除该代理仓库;Maven客户端直接使用“maven-public”组仓库即可,配置示例见配置示例1;“Release”版本的包发布到“maven-releases”仓库,配置示例见配置示例2;“Snapshot”版本的包发布到“maven-snapshots”仓库,配置示例见配置示例3
  • 配置示例1

    <repository>
      <id>maven-public</id>
      <name>Central Repository</name>
      <url>http://A:8081/repository/maven-public/</url>
      <layout>default</layout>
      <releases>
        <enabled>true</enabled>
      </releases>
      <snapshots>
        <enabled>true</enabled>
        <updatePolicy>always</updatePolicy>
      </snapshots>
    </repository>
    

    配置示例2

    # settings.xml
    # 仓库的用户名和密码必须在settings.xml文件中配置,id属性作为唯一标识不一定需要是对应的仓库名称
    <server>
      <id>maven-releases</id>
      <username>admin</username>
      <password>admin123</password>
    </server>
    # 命令行
    # 通过-D选项指定插件需要的系统变量 
    mvn deploy -Dmaven.test.skip=true -DaltDeploymentRepository=maven-releases::default::http://A:8081/repository/maven-releases/
    mvn deploy:deploy-file -Dfile={待上传包路径} -DgroupId={包上传后的GroupId} -DartifactId={包上传后的ArtifactId} -Dversion={包上传后的版本号} -Dpackaging={包上传后的类型,一般为JAR} -DrepositoryId=maven-releases -Durl=http://A:8081/repository/maven-releases/
    

    配置示例3

    # settings.xml
    # 仓库的用户名和密码必须在settings.xml文件中配置,id属性作为唯一标识不一定需要是对应的仓库名称
    <server>
      <id>maven-snapshots</id>
      <username>admin</username>
      <password>admin123</password>
    </server>
    # 命令行
    # 通过-D选项指定插件需要的系统变量 
    mvn deploy -Dmaven.test.skip=true -DaltDeploymentRepository=maven-snapshots::default::http://A:8081/repository/maven-snapshots/
    mvn deploy:deploy-file -Dfile={待上传包路径} -DgroupId={包上传后的GroupId} -DartifactId={包上传后的ArtifactId} -Dversion={包上传后的版本号} -Dpackaging={包上传后的类型,一般为JAR} -DrepositoryId=maven-snapshots -Durl=http://A:8081/repository/maven-snapshots/
    

    备注:
    上传到“maven-releases”仓库的JAR包“version”设置中禁止含有“SNAPSHOT”字符串;反之,上传到“maven-snapshots”仓库的JAR包“version”设置中必须含有“SNAPSHOT”字符串

    2.2.2、B节点

    B节点具体搭建Nexus具体流程如下:

  • 修改“bin/nexus”执行脚本中的INSTALL4J_JAVA_HOME_OVERRIDE变量,将其值设为1.8以上JDK的路径
  • 冷拷贝A节点上的Nexus数据目录“sonatype-work”
  • 执行bin/nexus start开启Nexus服务
  • 2.2.3、C节点

    C节点具体搭建Nexus具体流程如下:

  • 修改“bin/nexus”执行脚本中的INSTALL4J_JAVA_HOME_OVERRIDE变量,将其值设为1.8以上JDK的路径
  • 冷拷贝A节点上的Nexus数据目录“sonatype-work”
  • 执行bin/nexus start开启Nexus服务
  • 2.3、搭建Nginx

    具体选用Nginx-1.13.8版本,非root用户安装和使用Nginx。
    参考[2],搭建Nginx具体流程如下:

  • https://sourceforge.net/projects/pcre/files/pcre/下载最新的PCRE包,解压
  • 解压Nginx包,进入解压后目录
  • 执行./configure --prefix={Nginx安装到目录} --with-pcre={PCRE包路径} --without-http_gzip_module && make && make install命令,完成安装
  • 进入安装到目录,配置“conf/nginx.conf”文件,需要注意的是,由于是非root用户使用Nginx,监听端口需要大于1024,一个示例配置见Nginx示例配置
  • 进入安装到目录,执行sbin/nginx开启Nginx服务
  • Nginx示例配置

    #user  nobody;
    worker_processes  1;
    #error_log  logs/error.log;
    #error_log  logs/error.log  notice;
    #error_log  logs/error.log  info;
    #pid        logs/nginx.pid;
    events {
        worker_connections  1024;
    http {
        upstream myapp1 {
            #可以解决同一个会话的一系列请求被转发到不同服务器导致cookie获取异常的问题
            ip_hash;
            server A:8081;
            server B:8081;
            server C:8081;
        server {
            listen 8081;
            location / {
                allow 允许IP地址1;
                allow 允许IP地址2;
                allow 允许IP地址3;
                deny all;
                proxy_pass http://myapp1;
                proxy_set_header Host $host:$server_port;
    参考文献:
    [1]http://www.sonatype.org/nexus/2015/07/10/high-availability-ha-and-continuous-integration-ci-with-nexus-oss
    [2]https://gist.github.com/simonw/92481
    [3]https://help.sonatype.com/display/NXRM3/Run+Behind+a+Reverse+Proxy
    [4]http://nginx.org/en/docs/http/load_balancing.html
    [5]https://ketao1989.github.io/2015/08/30/nginx-proxy-configure-and-sduty/
    [6]http://www.cnblogs.com/xianyulaodi/p/6547807.html
    [7]https://serverfault.com/questions/598202/make-nginx-to-pass-hostname-of-the-upstream-when-reverseproxying
    [8]https://trac.nginx.org/nginx/ticket/501
    [9]http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header
    [10]http://blog.51cto.com/1234567aaa/317802
    [11]http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream
    [12]https://www.liaoxuefeng.com/article/001463233913442cdb2d1bd1b1b42e3b0b29eb1ba736c5e000