跳转至

部署

多环境

什么是多环境

多环境:指同一套项目代码在不同的阶段需要根据实际情况来调整配置并且部署到不同的机器上。

为什么需要?

  1. 每个环境互不影响
  2. 区分不同的阶段:开发 / 测试 / 生产
  3. 对项目进行优化:
    1. 本地日志级别
    2. 精简依赖,节省项目体积
    3. 项目的环境 / 参数可以调整,比如 JVM 参数

针对不同环境做不同的事情。

多环境分类

  1. 本地环境(自己的电脑):localhost
  2. 开发环境(远程开发)大家连同一台机器,为了大家开发方便
  3. 测试环境(测试)开发 / 测试 / 产品,单元测试 / 性能测试 / 功能测试 / 系统集成测试,独立的数据库、独立的服务器
  4. 预发布环境(体验服):和正式环境一致,正式数据库,更严谨,查出更多问题
  5. 正式环境(线上,公开对外访问的项目):尽量不要改动,保证上线前的代码是 “完美” 运行
  6. 沙箱环境(实验环境):为了做实验

前端多环境

serve工具的安装

# npm install -g serve

yarn global add serve

前端静态化:在一些场景中,无法做服务端的 html fallback,即让每个路由都输出 index.html 的内容。那么就要做静态化,让每一个组件都生成一个index.html文件

后端多环境

通过 application-dev.yml 与 application-prod.yml 区分环境

  • 数据库地址
  • 缓存地址
  • 端口号
  • content path

数据库建表之后及时备份 ( /sql )

项目部署

原生部署

前端部署

打包前端 dist 文件,上传到服务器

使用nginx部署

后端部署

后端打包:使用maven package命令

跳过测试:

安装java17

cd /usr/local
wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz
tar -zxvf jdk-17_linux-x64_bin.tar.gz 

在启动项目时传入环境变量,区分运行环境

java -jar .\user-center-backend-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod

后台运行 jar 包

nohup java -jar .\user-center-backend-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod &

后端需要到服务器上,使用maven打包

# 打包构建,跳过测试
mvn package -DskipTests

容器 Docker

将项目依赖的环境、软件、代码打包成镜像,方便分发和移植。启动项目时,不需要敲一大堆命令,而是直接下载镜像、启动镜像就可以了。

制作镜像:Dockerfile 用于指定构建 Docker 镜像的方法

Dockerfile 一般情况下不需要完全从 0 自己写,建议去 github、gitee 等托管平台参考同类项目(比如 springboot)

Dockerfile 编写:

  • FROM 依赖的基础镜像
  • WORKDIR 工作目录
  • COPY 从本机复制文件
  • RUN 执行命令
  • CMD / ENTRYPOINT(附加额外参数)指定运行容器时默认执行的命令

后端:

FROM maven:3.5-jdk-8-alpine as builder

# Copy local code to the container image.
WORKDIR /app
COPY pom.xml .
COPY src ./src

# Build a release artifact.
RUN mvn package -DskipTests

# Run the web service on container startup.
CMD ["java","-jar","/app/target/user-center-backend-0.0.1-SNAPSHOT.jar","--spring.profiles.active=prod"]

前端:

FROM nginx

WORKDIR /usr/share/nginx/html/
USER root

COPY ./docker/nginx.conf /etc/nginx/conf.d/default.conf

COPY ./dist  /usr/share/nginx/html/

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]
server {
    listen 80;

    # gzip config
    gzip on;
    gzip_min_length 1k;
    gzip_comp_level 9;
    gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml;
    gzip_vary on;
    gzip_disable "MSIE [1-6]\.";

    root /usr/share/nginx/html;
    include /etc/nginx/mime.types;

    location / {
        try_files $uri /index.html;
    }
}

根据Dockerfile去制作镜像

sudo docker build -t user-center-backend:v0.0.1 .

Docker启动

# 前端
docker run -p 80:80 -d user-center-frontend:v0.0.1

# 后端
docker run -p 8080:8080 -d user-center-backend:v0.0.1

虚拟化

  1. 端口映射:把本机的资源(实际访问地址)和容器内部的资源(应用启动端口)进行关联
  2. 目录映射:把本机的端口和容器应用的端口进行关联

Docker其他命令

# 杀死容器
docker kill [container-id]

# 强制删除镜像
docker rmi -f [container-id]

# 查看进程
docker ps

# 进入容器
docker exec -i -t [container-id] /bin/bash

# 查看日志
docker logs -f [container-id]

容器平台

  1. 腾讯云、阿里云
  2. 微信云托管

应用托管平台

适用于前端,导入git项目部署。可以自动构建。

  • Webify

跨域问题

浏览器为了用户的安全,仅允许向 同域名、同端口 的服务器发送请求。

解决跨域

1、把域名、端口改成相同的

2、网关支持 (Nginx) :让服务器告诉浏览器:允许跨域(返回 cross-origin-allow 响应头)

location ^~ /api/ {
    proxy_pass http://127.0.0.1:8080/api/;
    add_header 'Access-Control-Allow-Origin' $http_origin;
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
    add_header Access-Control-Allow-Headers '*';
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Origin' $http_origin;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        add_header 'Content-Length' 0;
        return 204;
    }
}

3、修改后端服务

① 配置 @CrossOrigin 注解

@CrossOrigin(origins = "https://rexhao.work")

② 添加 web 全局请求拦截器

//解决跨域问题
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //添加映射路径
        registry.addMapping("/**")
                //是否发送Cookie
                .allowCredentials(true)
                //设置放行哪些原始域   SpringBoot2.4.4下低版本使用.allowedOrigins("*")
                .allowedOriginPatterns("*")
                //放行哪些请求方式
//                .allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"})
                .allowedMethods("*") //或者放行全部
                //放行哪些原始请求头部信息
                .allowedHeaders("*")
                //暴露哪些原始请求头部信息
                .exposedHeaders("*");
    }

    // 当前跨域请求最大有效时长。这里默认1天
    private static final long MAX_AGE = 24 * 60 * 60;

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址
        corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
        corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
        corsConfiguration.setMaxAge(MAX_AGE);
        source.registerCorsConfiguration("/**", corsConfiguration); // 4 对接口配置跨域设置
        return new CorsFilter(source);
    }
}

Vue的history问题

Vue使用history模式路由(/win、/admin),会导致直接输入hpan.wmhwiki.cn/win报404错误。

原因:路由是js实现的,并不存在/win/index.html目录

解决:进行一个Nginx的配置

location / {
    try_files $uri $uri/ /index.html;
}