用户中心项目部署

项目部署

多环境介绍

多环境是指在项目开发和运营的过程中,使用多个独立的环境来运行、测试和发布应用程序。每个环境互不影响,便于开发团队更好地管理代码的不同阶段,以及确保在不同环境中应用的稳定性和性能。

在实际项目开发中,需要面对不同的运行环境,比如开发环境、测试环境、生产环境等,每个运行环境的数据库、Redis 服务器等配置都不相同,每次发布测试、更新生产都需要手动修改相关系统配置。

前端多环境配置

基于 Umi 设置多环境也可以看看这篇:https://blog.csdn.net/wangkun881112/article/details/140951260

请求地址

  • 开发环境:localhost:8000
  • 线上环境:(你自己的网站域名)

根据运行环境更换地址

我们需要在 request 的配置路径上通过判断

请求地址要根据当前运行环境配置。

我们查看代码可以看到有两个地方和环境变量有关,这两个的区别在于 process.env.NODE_ENV 是根据启动命令自动添加的(仅Umi框架)。而 REACT_APP_ENV 是查看项目中是否有自定义的环境变量,根据自定义变量来判断的当前环境,也就是说在不同的环境变量还是需要手动修改变量。

所以我们在这里通过 process.env.NODE_ENV 来更换不同的请求地址。

test03\src\app.tsx 代码如下:

tsx
复制代码
const isProd = process.env.NODE_ENV === 'production'; ... /** * @name request 配置,可以配置错误处理 * 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。 * @doc https://umijs.org/docs/max/request#配置 */ export const request = { ...errorConfig, baseURL: isP ? 'http://meliry.top' : undefined, };

【拓展】脚本自动添加环境 process.env.NODE_ENV

test03\src\app.tsx下面有:

tsx
复制代码
const isDev = process.env.NODE_ENV === 'development';

参考上面的代码,我们就可以在 request 的配置下为不同的运行环境配置不同的请求地址了。

由于在前面我们设置了正向代理,所以在开发环境下我们可以不用更改请求地址。

但我们并不可以直接在代理配置那里通过更改代理地址来更改请求地址,因为我们查看代理的配置文件,可以看到并没有为生产环境设置代理的默认配置,且在其注解中写明了在生产环境 代理是无法生效的,所以这里没有生产环境的配置

这里需要注意的是,Umi 在不同的运行命令下,会自动为 process.env.UMI_ENV 赋值:

  • npm run start :process.env.NODE_ENV 为 development
  • npm run build :process.env.NODE_ENV 为 production
  • npm run test :process.env.NODE_ENV 为 test

【拓展】自定义运行环境 REACT_APP_ENV

test03\config**\config.ts文件中,提取自定义的运行环境:**

tsx
复制代码
const { REACT_APP_ENV = 'dev' } = process.env;

process.env 是 Node.js 的一个全局对象,包含当前进程的环境变量。不同环境(开发环境、测试环境、生产环境)可以通过配置不同的环境变量文件或者设置不同的环境变量来控制应用的行为。

{ REACT_APP_ENV = 'dev' }:这是一种解构赋值的写法。它尝试从 process.env 中提取 REACT_APP_ENV 的值,如果 REACT_APP_ENV 在环境变量中不存在,代码会将 REACT_APP_ENV 的值设置为 dev。

启动方式

可以通过不同的项目启动命令启动不同的环境:

bash
复制代码
# 启动开发环境(本地启动,监听端口,自动更新) npm run start # 启动生产环境(项目构建打包) npm run build # 启动测试环境 npm run test

配置文件

不同的项目(框架)都有不同的配置文件。

Umi 框架支持根据不同的环境配置多环境。通常使用 config/config[env].js/ts文件来实现多环境配置。在 Umi 框架中,这些配置文件会根据不同的环境变量自动加载。

  • 开发环境:config.dev.js (或 config.dev.ts)
  • 生产环境:config.prod.js (或 config.prod.ts)
  • 测试环境:config.test.js (或 config.test.ts)

后端多环境配置

配置文件

SpringBoot 可以通过使用 application.properties(或 application.yml) ,结合不用的配置文件后缀,实现多环境的配置。

src/main/resources 目录下:

  • application.propertiea:通用配置文件
  • application-dev.properties:开发环境配置文件
  • application-prod.properties:生产环境配置文件

修改完不同的配置文件后,使用 maven 带的 package 进行打包,运行命令:

bash
复制代码
java -jar ./user-center-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod

注意看当前命令窗口的 java 版本是否大于或等于项目的 java 版本,决定是否能运行,且如果用 idea 运行的话,切换了 java 版本需要重启电脑才能在 idea 的终端中生效,cmd 则不用。

运行结果如下,注意看一行,标明了当前运行环境!

bash
复制代码
2024-10-08 10:37:22.875 INFO 8560 --- [ main] c.m.usercenter.UserCenterApplication : The following 1 profile is active: "prod" 2024-10-08 10:37:24.881 INFO 8560 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8800 (http) 2024-10-08 10:37:24.908 INFO 8560 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2024-10-08 10:37:24.908 INFO 8560 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.65] 2024-10-08 10:37:25.015 INFO 8560 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/api] : Initializing Spring embedded WebApplicationContext 2024-10-08 10:37:25.015 INFO 8560 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2058 ms _ _ |_ _ _|_. ___ _ | _ | | |\/|_)(_| | |_\ |_)||_|_\ / | 3.4.1 2024-10-08 10:37:26.042 INFO 8560 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8800 (http) with context path '/api' 2024-10-08 10:37:26.055 INFO 8560 --- [ main] c.m.usercenter.UserCenterApplication : Started UserCenterApplication in 3.699 seconds (JVM running for 4.121)

推荐修改的配置

由于我这里并没有线上的地址,所以这里整理配置为多环境时可能需要修改配置

主要修改的配置有以下部分:

  • 依赖的环境地址
    • 数据库地址
    • 缓存地址
    • 消息队列地址
    • 项目端口号
  • 服务器配置

Linux安装Nginx

教程参考:https://blog.csdn.net/weixin_47962813/article/details/141251944

下载Nginx并解压

Nginx官网下载:https://nginx.org/en/download.html

下载稳定版本(Stable version),名称为 nginx-1.26.2 类似。

下载完后传输到云服务器上,我用的是 xftp。

解压文件:

shell
复制代码
tar -zxvf nginx-1.26.2.tar.gz

安装Nginx

1、检查 Linux 是否有 Nginx 的依赖环境:

shell
复制代码
./configure

运行结果(后面显示Nginx的新的配置文件的位置):

shell
复制代码
Configuration summary + using system PCRE library + OpenSSL library is not used + using system zlib library nginx path prefix: "/usr/local/nginx" nginx binary file: "/usr/local/nginx/sbin/nginx" nginx modules path: "/usr/local/nginx/modules" nginx configuration prefix: "/usr/local/nginx/conf" nginx configuration file: "/usr/local/nginx/conf/nginx.conf" nginx pid file: "/usr/local/nginx/logs/nginx.pid" nginx error log file: "/usr/local/nginx/logs/error.log" nginx http access log file: "/usr/local/nginx/logs/access.log" nginx http client request body temporary files: "client_body_temp" nginx http proxy temporary files: "proxy_temp" nginx http fastcgi temporary files: "fastcgi_temp" nginx http uwsgi temporary files: "uwsgi_temp" nginx http scgi temporary files: "scgi_temp"

OpenSSL 是和配置 HTTPS 相关的库,这里显示没有使用,如果后续需要配置 HTTPS ,则需要安装该库。

shell
复制代码
yum -y install openssl openssl-devel

然后重新检查环境:

设置系统参数:

--with-http_stub_status_module:用来监控 Nginx 的当前状态

--with-http_ssl_module:使用https协议模块。默认情况下,该模块没有被构建。前提是openssl与openssl-devel已安装

shell
复制代码
./configure --with-http_ssl_module

2、编译

shell
复制代码
make

3、安装

shell
复制代码
make install

4、启动

查看 Nginx 安装目录:

shell
复制代码
whereis nginx 结果: nginx: /usr/local/nginx

进入安装目录里的 sbin 目录里面,启动:

shell
复制代码
cd /usr/local/nginx/sbin/ ./nginx

查看 Nginx 进程:

shell
复制代码
[root@ubten3uk4bm9hvco sbin]# ps -ef | grep nginx root 19373 1 0 15:40 ? 00:00:00 nginx: master process ./nginx nobody 19374 19373 0 15:40 ? 00:00:00 nginx: worker process root 19398 2688 0 15:41 pts/1 00:00:00 grep --color=auto nginx

nginx 基本命令

shell
复制代码
1、启动Nginx ./nginx 2、关闭Nginx ./nginx -s stop 3、重启Nginx ./nginx -s reopen 4、重新载入配置文件 ./nginx -s reload

配置 Nginx 环境变量:

进入 profile 文件:

shell
复制代码
vim /etc/profile

文件末尾添加环境变量:

shell
复制代码
# nginx 环境变量 export PATH=$PATH:/usr/local/nginx/sbin

重新加载环境变量:

shell
复制代码
source /etc/profile

首先需要把前后端打包完的文件全部传入服务器中。

前端部署

通过修改 nginx.conf 来修改 Nginx 服务器的目录,从而运行前端项目。

shell
复制代码
vim /usr/local/nginx/conf/nginx.conf

需要注意的是 Nginx 的配置文件已经全部在 /etc/local/nginx/conf 目录下,而不是在之前的安装目录下,注意不要修改错了。

默认配置:

shell
复制代码
location / { root html; index index.html index.htm; }

将 root 修改为前端项目的目录,再重新配置 Nginx 配置文件即可。

端口不通可参考:https://www.ctyun.cn/document/10026730/10243885#p-f130cd67149faf42

后端部署

安装java

查看 yum 可安装的 java 版本:

shell
复制代码
yum list | grep jdk

安装对应版本:

shell
复制代码
yum install java-1.8.0-openjdk-devel.x86_64

由于我项目里用的是 java17 的版本,但这里最高只有 java11,所以我选择官网下载再上传。

java 官网:https://www.oracle.com/cn/java/technologies/downloads/#java17

下载后解压,再把 bin 目录配置到系统环境变量即可。

运行后端项目

shell
复制代码
java -jar ./user-center-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod

直接终端运行即可。由于我没有线上的数据库,且本地没有安装 MySQL ,所以这里可以用,但没有数据。

如果想要在后台运行可以使用:

shell
复制代码
nohup java -jar ./user-center-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod &

不推荐后台启动,看不见运行日志,且不好关闭,不如再开一个窗口。

域名解析

流程

1、用户请求域名

当用户在浏览器中输入一个域名时,系统会先检查是否已经有对应的 IP 地址缓存,以避免重复查询。缓存可能存在于:

  • 浏览器缓存:浏览器会缓存最近访问过的域名及其 IP 地址。
  • 操作系统缓存:本地计算机的 DNS 缓存(通过 ipconfig/displaydns 查看 Windows 缓存)。
  • 本地 hosts 文件:操作系统可能在 hosts 文件中手动配置了一些域名解析规则。

如果缓存中有匹配的 IP 地址,则直接返回改地址,无需进一步查询。如果缓存中没有结果,则开始域名解析的完整过程。

2、DNS 递归解析器

如果本地没有找到缓存的结果,操作系统会向 DNS 递归解析器(通常由 ISP 或 DNS 提供商提供)发送查询请求。递归解析器负责代表客户端向各类 DNS 服务器请求 IP 地址。

3、检查递归解析器缓存

DNS 递归解析器首先会检查自己的缓存。如果有结果,解析器会将 IP 地址返回给客户端,如果没有缓存结果,解析器会开始递归查询过程,向其他 DNS 服务器请求结果。

4、查询根域名服务器

DNS 递归解析器首先查询根域名服务器(Root Name Servers)。根域名服务器存储了有关顶级域名(TLD,如 .com.org.net)的信息,并且知道如何找到相应的顶级域名服务器。

根域名服务器不会返回最终的 IP 地址,而是返回负责该 TLD 的顶级域名服务器的地址。全球有 13 个根域名服务器集群(如 a.root-servers.net, b.root-servers.net 等)。

5、查询顶级域名服务器(TLD服务器)

递归解析器接收到根域名服务器的响应后,向相应的顶级域名服务器发送查询请求(例如,对于 www.example.com,它会查询 .com TLD 服务器)。

TLD 服务器负责维护该顶级域的所有域名的权威 DNS 服务器信息。TLD 服务器不会返回最终的 IP 地址,而是返回该域名的权威 DNS 服务器的地址。

6、查询权威 DNS 服务器

递归解析器接收到 TLD 服务器的响应后,向域名的 权威 DNS 服务器发送查询请求(例如,对于 www.example.com,会查询 example.com 的权威 DNS 服务器)。权威 DNS 服务器保存域名与 IP 地址的最终映射关系。

权威 DNS 服务器返回该域名的 A 记录(IPv4 地址)或 AAAA 记录(IPv6 地址),解析器将 IP 地址返回给客户端。

7、客户端接收 IP 地址

递归解析器将域名对应的 IP 地址返回给客户端。客户端(如浏览器)现在可以使用该 IP 地址与目标服务器建立连接,发送 HTTP 请求或其他网络通信。

缓存优化

为了优化性能并减少 DNS 请求数量,解析结果会被缓存:

  • 递归解析器缓存:缓存一段时间(通常由域名的 TTL 值决定)。
  • 操作系统缓存:操作系统会缓存 IP 地址以便快速访问。
  • 浏览器缓存:浏览器也会短时间缓存结果。

解析流程总结及示例

总结:

  1. 用户请求域名 → 浏览器/操作系统缓存 → DNS 递归解析器。
  2. DNS 递归解析器 → 根域名服务器 → 顶级域名服务器(TLD) → 权威 DNS 服务器。
  3. 权威 DNS 服务器 返回 IP 地址 → 递归解析器返回给客户端。
  4. 客户端使用 IP 地址 访问目标服务器。

示例:

假设用户输入 www.example.com

  1. 浏览器检查缓存,没有找到 IP。
  2. 操作系统检查本地缓存或 hosts 文件,也没有找到。
  3. 操作系统将查询发送到 DNS 递归解析器(例如 Google 的 8.8.8.8)。
  4. 递归解析器向根域名服务器查询,根域名服务器返回 .com TLD 服务器的地址。
  5. 递归解析器向 .com TLD 服务器查询,TLD 服务器返回 example.com 的权威 DNS 服务器地址。
  6. 递归解析器向权威 DNS 服务器查询,权威服务器返回 www.example.com 的 IP 地址。
  7. 递归解析器将 IP 地址返回给操作系统,操作系统返回给浏览器。
  8. 浏览器使用 IP 地址与 www.example.com 的服务器建立连接。

跨域问题

后端配置跨域

最简单的就是后端配置跨域了,也就是在需要跨域的控制器上添加注解@CrossOrigin

错误参考

1、拦截器把登录页面可注册页面也拦截了

F12 查看请求,可以发现有/user/login/user/login/两个请求。

原因:Nginx 默认配置中,如果用户访问一个路径而没有以/结尾,Nginx 可能会自动重定向到带/结尾的路径。

所以,为了让登录页面和注册页面不被拦截,需要在白名单里加上/user/login//user/register/两个路径。

2、登录成功但还是显示未登录

由于我们保存登录,使用的是保存用户的 id 在 session中,

原因:前端没有给后端传递 cookie,无法与后端存储的 session 相对应,导致前端登录失败。

需要前端配置允许传递 cookie。

app.tsx:

tsx
复制代码
/** * @name request 配置,可以配置错误处理 * 它基于 axios 和 ahooks 的 useRequest 提供了一套统一的网络请求和错误处理方案。 * @doc https://umijs.org/docs/max/request#配置 */ export const request = { ...errorConfig, baseURL: isProd ? '**********' : undefined, withCredentials: true, //允许跨域时携带cookie };

拓展

serve服务器

参考:https://blog.csdn.net/gitblog_00064/article/details/139515780

serve 适宜个用于静态文件服务的简单 Node.js 服务器。它通常用于快速启动一个 HTTP 服务器来提供静态文件,比如 HTTP、CSS、JavaScript 和图片等。

bash
复制代码
# 安装 npm install -g serve # 使用 serve <path>

如果要在当前文件夹启动,则用serve .

常用选项:

  • -s--single: 适用于单页应用程序(SPA),所有的路径都将返回 index.html
  • -l <port>: 指定监听的端口号,默认是 3000
  • -d--debug: 启用调试模式,显示详细的请求日志。

示例:

如果你想服务于 build 目录(例如 React 应用的构建目录)并在 5000 端口上运行,可以这样做:

bash
复制代码
serve -s build -l 5000

umi静态化配置exportStatic

静态化说明

官方文档:https://umijs.org/docs/api/config#exportstatic

静态化配置用于解决页面路由跳转的问题。exportStatus 静态化是 umi 框架里的一个配置。

在我们用 vue 、react 根据路由动态跳转的时候,会出现打包后的页面只能在一个页面上进行操作,一旦对该页面进行刷新后就会出现 404,并且访问页面也只能在首页,一旦加上 / 后再加地址,也是会出现 404。

而在之前我们有两种解决办法(vue),一种是修改 vue-router 为 hash 模式(react也可以修改),这种地址不雅观,会在地址上多一个 # 号;另一种则是修改运行静态文件的 web 服务器的配置,使其支持动态跳转。

关于 react 和 vue 路由配置 hash 模式的方式可以参考:https://blog.csdn.net/gu2022_3_5_21_23/article/details/140788415,也可以直接查看官方文档。

react 两种路由实现原理参考:https://blog.csdn.net/weixin_45620943/article/details/135401455

而对于 umi 框架里封装的 hash 路由配置方式则参考:https://umijs.org/docs/api/config#history

还有一个需要注意的点,在使用 hash 路由时,需要给 request 请求加上一个 /# 的前缀,否则跳转的链接会全部失效

现在,我们有了第三种方法,那就是在 umi 框架的配置文件中开启静态化。

不过 umi 好像现在只支持 react ,vue 那边暂时没看到用的。

配置方式

在 test03\config\config.ts 文件下,添加一个 exportStatic 的参数即可:

tsx
复制代码
exportStatic: {},

常见 DNS 记录类型

A 记录:将域名解析为 IPv4 地址。

AAAA 记录:将域名解析为 IPv6 地址。

CNAME 记录:将一个域名别名指向另一个域名。

MX 记录:定义邮件服务器的优先级。

NS 记录:指定域名的权威 DNS 服务器。

TXT 记录:存储任意文本信息,通常用于验证域名所有权或配置 SPF/DKIM 等邮件安全机制。

session 与 cookie 的协同工作

当用户登录后,服务器会创建一个 Session 并生成一个唯一的 Session ID

这个 Session ID 通过 Set-Cookie 头部传递给前端浏览器,并存储在浏览器的 Cookie 中。

在后续的每个请求中,浏览器会自动附带这个 Cookie(即 Session ID),服务器可以根据这个 Session ID 找到对应的用户会话信息。

为什么前端必须要传递 cookie?

Session ID 是存储在后端的会话的唯一标识符,后端需要通过 Session ID 来确认哪个用户在进行操作。

前端传递的 Cookie 中包含了 Session ID,因此后端通过这个 ID 来检索出与该用户关联的 Session 数据(如登录状态、用户信息等)。

没有 Cookie,后端无法知道该请求属于哪个用户,也就无法确认用户的身份。

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
Meliry
下载 APP