• 部署和上线项目踩坑


    多环境

    本地开发:localhost

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

    为什么需要?

    1. 每个环境互不影响
    2. 区分不同的阶段:开发 / 测试 / 生产(线上的配置高一点)
    3. 对项目进行优化:
      1. 本地日志级别
      2. 精简依赖,节省项目体积(lombok在编译项目时候就把get,set生成了,线上不需要这个插件)
      3. 项目的环境 / 参数可以调整,比如 JVM 参数

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

    多环境分类:

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

    前端多环境

    前端请求的地址是localhost:8000

    在请求一个网页资源的时候,首先把这些网站的文件,拿到自己的浏览器里,之后,如果说这个网页还需要依赖什么文件,我们都是从自己的电脑上发出的请求,所以这个localhost,其实请求的是我们自己的电脑。
    
    • 1

    请求地址

    • 开发环境:localhost:8000

    • 线上环境:http://usercenterp.jinxs.icu/

    startFront(env) {
        if(env === 'prod') {
            // 不输出注释 
            // 项目优化
            // 修改请求地址
        } else {
            // 保持本地开发逻辑
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    用了 umi 框架,build 时会自动传入 NODE_ENV == production 参数,start NODE_ENV 参数为 development

    • 启动方式

      • 开发环境:npm run start(本地启动,监听端口、自动更新)
      • 线上环境:npm run build(项目构建打包),可以使用 serve 工具启动(npm i -g serve)
    • 项目的配置

      不同的项目(框架)都有不同的配置文件,umi 的配置文件是 config,可以在配置文件后添加对应的环境名称后缀来区分开发环境和生产环境。参考文档:https://umijs.org/zh-CN/docs/deployment

      • 开发环境:config.dev.ts
      • 生产环境:config.prod.ts
      • 公共配置:config.ts 不带后缀
       npm i -g serve
      
      • 1

      cd到dist目录执行serve

      输入此命令,发现执行成功

      npm list -g --depth 0
      
      • 1

      把npm的本地仓库添加到环境变量

      然后进入到dist目录执行serve

      image-20220804161154213

      相当于在本地给你启动了一个外部服务器,可以在本地把咱们的这个网页文件放到这个服务器上,并且给你启动起来,让你能够访问。

      build+serve就可以在浏览器运行出现的alert是production

      访问3000端口

      image-20220730132820219

      静态化,其实就是做了一件什么事情?它是根据页面的路由,把每个路由都给你生成一个index.html,都给你生成一个静态文件
      
      • 1

    后端多环境实战

    SpringBoot 项目,通过 application.yml 添加不同的后缀来区分配置文件

    可以在启动项目时传入环境变量:

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

    主要是改:

    • 依赖的环境地址

      • 数据库地址

      • 缓存地址

      • 消息队列地址

      • 项目端口号

    • 服务器配置


    package打包

    cd target目录

    运行jar包并且传入参数

    java -jar .\user_center-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod
    
    • 1

    image-20220731224657585

    执行的是prod的配置文件


    原始部署

    前端

    需要 web 服务器:nginx 、apache、tomcat

    安装 nginx 服务器:

    1. 用系统自带的软件包管理器快速安装,比如 centos 的 yum

    2. 自己到官网安装(参考文章)

      curl -o nginx-1.21.6.tar.gz http://nginx.org/download/nginx-1.21.6.tar.gz
      
      tar -zxvf nginx-1.21.6.tar.gz
      
      cd nginx-1.21.6
      
         37  2022-04-17 23:30:09 yum install pcre pcre-devel -y
         39  2022-04-17 23:30:59 yum install openssl openssl-devel -y
         41  2022-04-17 23:31:57 ./configure --with-http_ssl_module --with-http_v2_module --with-stream
         42  2022-04-17 23:32:13 make
         43  2022-04-17 23:32:54 make install
         48  2022-04-17 23:33:40 ls /usr/local/nginx/sbin/nginx
         vim /etc/profile
        在最后一行添加:export PATH=$PATH:/usr/local/nginx/sbin	
        
        nginx
        
        netstat -ntlp 查看启动情况
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18

      注意 nginx 权限

      后端

      java、maven

      安装:

      yum install -y java-1.8.0-openjdk*
      
      curl -o apache-maven-3.8.5-bin.tar.gz https://dlcdn.apache.org/maven/maven-3/3.8.5/binaries/apache-maven-3.8.5-bin.tar.gz
      
      • 1
      • 2
      • 3

      解压

       tar -zxvf apache-maven-3.8.5-bin.tar.gz 
      
      • 1

      报错

    image-20220801104824864

    原来的这个网页打不开了

    https://dlcdn.apache.org/maven/maven-3/3.8.5/binaries/apache-maven-3.8.5-bin.tar.gz
    
    • 1

    换成这个网页

    curl -o apache-maven-3.0.5-bin.tar.gz https://dlcdn.apache.org/maven/binaries/apache-maven-3.0.5-bin.tar.gz
    
    • 1

    又报错了

    image-20220801105540980

    curl -o apache-maven-3.0.5-bin.tar.gz https://dlcdn.apache.org/maven/binaries/apache-maven-3.0.5-bin.tar.gz
    
    • 1

    重试一遍

    成功,然后解压

     tar -zxvf apache-maven-3.0.5-bin.tar.gz 
    
    • 1

    image-20220801110043262

    配置环境变量

    pwd查看当前路径

    编辑etc下的profile文件,shift+g跳到最后一行,按o加一行

    image-20220801230646942

    刷新一下

     source /etc/profile
    
    • 1

    到/root目录输入mvn -v

    配置成功

    image-20220801230831844

    安装git

    yum install git
    
    • 1

    打包构建,跳过测试

    mvn package -DskipTests
    
    • 1

    执行

    java -jar user_center-0.0.1-SNAPSHOT.jar --spring.profiles,active=prod
    
    //执行后如果显示没有权限;给这个文件添加可执行权限
    chmod a+x user_center-0.0.1-SNAPSHOT.jar
    //再ls就会发现user_center-0.0.1-SNAPSHOT.jar变成绿色了
    
    • 1
    • 2
    • 3
    • 4
    • 5

    当然这么用的话,这个窗口就不能做任何事了,被这个命令占满了,按ctrl+c中断它
    让它在后台运行

    [root@VM-8-2-centos user_center_backend]# nohup java -jar user_center-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod &
    [1] 29378
    
    • 1
    • 2

    输入jbs,发现正在运行

    image-20220802103015839

    输入netstat -ntlp

    image-20220802103111432

    jps查看运行的java程序

    image-20220802103142234

    宝塔 Linux 部署

    Linux 运维面板

    官方安装教程:https://www.bt.cn/new/download.html

    方便管理服务器、方便安装软件

    前端托管

    前端腾讯云 web 应用托管(比容器化更傻瓜式,不需要自己写构建应用的命令,就能启动前端项目)

    https://console.cloud.tencent.com/webify/new

    • 小缺点:需要将代码放到代码托管平台上
    • 优势:不用写命令、代码更新时自动构建

    Docker 部署

    docker 是容器,可以将项目的环境(比如 java、nginx)和项目的代码一起打包成镜像,所有同学都能下载镜像,更容易分发和移植。

    再启动项目时,不需要敲一大堆命令,而是直接下载镜像、启动镜像就可以了。

    docker 可以理解为软件安装包。

    Docker 安装:https://www.docker.com/get-started/ 或者宝塔安装

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

    特别好用的一个镜像maven:3.5-jdk-8-alpine

    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-0.0.1-SNAPSHOT.jar","--spring.profiles.active=prod"]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

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

    Dockerfile 编写:

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

    根据 Dockerfile 构建镜像:

    # 后端
    docker build -t user-center-backend:v0.0.1 .
    表示使用当前目录的dockerfile构建镜像
    
    • 1
    • 2
    • 3

    报错

    image-20220802211451041

    创建镜像的时候指定dockerFile文件

    docker build -t user-center-front:v0.0.1 -f dockerfile .
    
    • 1

    DockerFile

    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;"]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    nginx,conf

    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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    构建镜像(前端)

    docker build -t user-center-front:v0.0.1 -f /docker/DockerFIle .
    
    • 1

    Docker 构建优化:减少尺寸、减少构建时间(比如多阶段构建,可以丢弃之前阶段不需要的内容)

    docker run 启动:

    # 前端
    docker run -p 57:80 -v /www/wwwroot/user_center/dockervdirectory/front_center:/usr/share/nginx/html/ -d user-center-front:v0.0.1
    
    # 后端
    docker run -p 8080:8080 user-center-backend:v0.0.1
    
    • 1
    • 2
    • 3
    • 4
    • 5

    虚拟化

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

    进入容器:

    docker exec -it  fee2bbb7c9ee /bin/bash
    
    • 1

    发现是空的

    image-20220803203052626

    映射目录出问题了,先不映射了

    docker run -p 57:80 -d user-center-front:v0.0.1
    docker run -p 3456:8080 -d user-center-cen:v0.0.1
    
    • 1
    • 2

    查看进程:

    docker ps 
    
    • 1

    查看日志:

    docker logs -f [container-id]
    //-f跟踪日志输出
    
    • 1
    • 2

    杀死容器:

    docker kill
    
    • 1

    强制删除镜像:

    docker rmi -f
    
    • 1

    Docker 平台部署

    1. 云服务商的容器平台(腾讯云、阿里云)
    2. 面向某个领域的容器平台(前端 / 后端微信云托管)要花钱!

    容器平台的好处:

    1. 不用输命令来操作,更方便省事
    2. 不用在控制台操作,更傻瓜式、更简单
    3. 大厂运维,比自己运维更省心
    4. 额外的能力,比如监控、告警、其他(存储、负载均衡、自动扩缩容、流水线)

    绑定域名

    前端项目访问流程:用户输入网址 => 域名解析服务器(把网址解析为 ip 地址 / 交给其他的域名解析服务) => 服务器 =>(防火墙)=> nginx 接收请求,找到对应的文件,返回文件给前端 => 前端加载文件到浏览器中(js、css) => 渲染页面

    后端项目访问流程:用户输入网址 => 域名解析服务器 => 服务器 => nginx 接收请求 => 后端项目(比如 8080端口)

    nginx 反向代理的作用:替服务器接收请求,转发请求

    添加一个dns解析用于后端

    image-20220804143546998

    每次访问都加个端口不太合适呀

    image-20220804143938097

    如果不加端口访问的是80端口,nginx,那我们可以用nginx反向代理,当访问配置的域名时,访问需要的端口就可以解决了

    nginx反向代理是非常常用的一个方法。可以帮我们统一的管理请求、接收请求,我们只需要去配置访问哪个域名、转发到哪个地址、转发到哪个项目,或者说访问哪个域名、访问哪个目录的文件
    
    • 1

    宝塔建个站点,配置反向代理

    image-20220804144022053

    再次访问域名,不加端口,成功

    image-20220804144042368

    登录前端,尝试下能否跑通,报错

    image-20220804144253025

    跨域问题

    用nginx解决跨域问题,把之前宝塔配置的反向代理给删掉自己写(顺便)

    # 跨域配置
    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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    跨域问题解决

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

    如何解决跨域?

    最直接的方式:把域名、端口改成相同的

    添加跨域头

    让服务器告诉浏览器:允许跨域(返回 cross-origin-allow 响应头)

    1. 网关支持(Nginx)

    # 跨域配置
    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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2. 修改后端服务

    1. 配置 @CrossOrigin 注解

    2. 添加 web 全局请求拦截器

      @Configuration
      public class WebMvcConfg implements WebMvcConfigurer {
       
          @Override
          public void addCorsMappings(CorsRegistry registry) {
              //设置允许跨域的路径
              registry.addMapping("/**")
                      //设置允许跨域请求的域名
                      //当**Credentials为true时,**Origin不能为星号,需为具体的ip地址【如果接口不带cookie,ip无需设成具体ip】
                      .allowedOrigins("http://localhost:9527", "http://127.0.0.1:9527", "http://127.0.0.1:8082", "http://127.0.0.1:8083")
                      //是否允许证书 不再默认开启
                      .allowCredentials(true)
                      //设置允许的方法
                      .allowedMethods("*")
                      //跨域允许时间
                      .maxAge(3600);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
    3. 定义新的 corsFilter Bean,参考:https://www.jianshu.com/p/b02099a435bd

  • 相关阅读:
    64.C++运算符重载
    前端面试基础面试题——6
    设计模式与应用:访问者模式
    java计算机毕业设计vue架构云餐厅美食订餐系统源码+mysql数据库+系统+lw文档+部署
    [iOS]static、extern、const关键字比较
    使用VSCode新建解决方案,添加ClassLib类库工程
    低开开发笔记(二):低代码编辑器基本原理
    umi+react+dva 配置request的全局配置(请求拦截与响应拦截)和调用请求
    如何为勒索软件攻击做准备?
    R语言ggplot2可视化:使用ggpubr包的ggarrange函数将多幅图像组合起来、使用ncol参数指定组合图列的个数
  • 原文地址:https://blog.csdn.net/qq_46110710/article/details/126161608