50持续集成:Java程序的部署

应用的开发流程

  • 产品调研
  • 产品设计
  • 系统设计
  • 开发
  • 测试
  • 部署

Web应用是如何工作的?

  • 每个HTTP请求的背后都是一台主机
  • 主机上的一个进程监听着某个端口
  • Java?
  • Go?
  • Python?
  • Nodejs?

什么是分布式?

  • 当访问的用户太多,怎么办?
    • 垂直扩展:买更好的机器
    • 水平扩展:加机器
    • 能用加机器解决的问题都不是问题
  • 那要如何保证数据的唯一性?
    • 单一数据源

部署和发布

  • 将开发好的程序放在服务器上,使之可以:
    • 监听端口
    • 响应HTTP请求
    • 进行预定义的业务逻辑处理
  • 产品还在不停地迭代
    • 部署的版本需要不停的进行更新
  • 分布式更新

发布和部署要解决的问题

  • 环境问题
    • 开发环境(测试环境)
    • 预发布环境(预生产环境)
    • 生产环境(正式环境)
  • 环境的兼容性问题
    • 硬件/软件
    • 数据库等

发布和部署Java程序

  • 使之在生产环摸下可以运行
  • 需要解决的问题
    • 自己编写的代码
    • 所依赖的第三方库
    • 所依赖的特殊环境配置(数据库/缓存等)
    • 稳定性(挂了怎么办?)
    • 升级和回滚

部署方式 1:使用Maven exec plugin

  • 自动将所有的传递性依赖加入
  • 优点:简单
  • 缺点:不适用于自动化的场景
  • 执行命令mvn exec:exec
  • 命令行前半部分是可执行程序,冲环境变量PATH里面找,后半部是参数
  • 绑定到比较靠后的阶段,使得mvn在运行这个插件之前已经执行compile编译成字节码

部署方式 2:使用jar包方式部署

  • 什么是jar包

    • 实际上就是编译后的代码资源打包
  • 什么样的jar包可以直接运行

    • jar包与Manifest
  • 优点:简单可靠

  • 缺点:依赖于JVM环境

打包mvn package

  • java -jar gs-spring-boot-0.1.0.jar 和 java -classpath con.xxx.xxx.Main 没区别

  • jar包里面有一个清单文件META-INF/MANIFEST.MF,文件里面有一个Main-Class配置

  • 部署之后修改配置文件

java程序启动的时候修改端口

  • java -Dserver.port=8081 -jar target/hahahaha-0.1.0.jar
    • targ/hahahaha-0.1.0.jar左边属于java命令行参数
    • targ/hahahaha-0.1.0.jar右边属于程序的命令行参数,会被传递到main方法的args里面

部署方式 3:docker方式部署

Docker运行Java程序

  • 创建镜像,Dockerfile文件
FROM java:openjdk-8u111-alpine

RUN mkdir /app

WORKDIR /app

COPY target/gs-spring-boot-0.1.0.jar /app

EXPOSE 8080

CMD [ "java", "-jar:, "gs-spring-boot-0.1.0.jar" ]

docker build .

  • docker容器内java程序连接Redis和MySQL

    • 在docker容器里创建一个application.prpeties文件覆盖掉jar包的默认配置文件,把localhost修改为宿主机的局域ip

    • spring.datasource.url=jdbc:mysql://192.168.200.100:3306/mall?characterEncoding=utf-8
      spring.datasource.username=root
      spring.datasource.password=123456
      # 请勿改变Redis端口号
      spring.redis.host=192.168.200.100
      spring.redis.port=6379
      # MyBatis 配置
      mybatis.config-location=classpath:/db/mybatis/config.xml
      # CGLIB来实现AOP的配置
      spring.aop.proxy-target-class=true
  • 启动java程序镜像

    • docker run -v 绝对路径/application.prperties:/app/config/pplication.prperties -p 8082:8080 镜像id

Docker运行数据库

  • docker run -d MYSQL_ROOT_PASSWORD=password -p 3306:3306 mysql

Docker运行Redis

  • docker run -p 6379:6379 -d redis

Docker运行Nginx

  • docker run --restart=always -v /host/path/nginx.conf:/etc/nginx/nginx.conf:ro -p 80:80 -d nginx

  • nginx.conf

    • events{ }
      http {
      upstream myapp1 {
          server 192.168.200.100:8080;
          server 192.168.200.100:8081;
          server 192.168.200.100:8082;
      }
      
      server {
          listen 80;
      
          location / {
              proxy_pass http://myapp1;
          }
      }
      }
  • 因为docker和宿主机隔离,要解决配置文件的server生效

    • hosts文件映射
    • 使用宿主机的局域网ip

「资料来源:饥人谷」

点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注