一、设置二级域名虚拟主机
在某某云上购买了域名之后,就可以配置虚拟主机了,一般配置的路径在 域名管理 -> 解析 -> 添加记录
中添加二级域名,配置后某某云会把二级域名也解析到我们配置的服务器 IP 上,然后我们在 Nginx 上配置一下虚拟主机的访问监听,就可以拿到从这个二级域名过来的请求了。
现在我自己的服务器上配置了一个 fe 的二级域名,也就是说在外网访问 fe.sherlocked93.club
的时候,也可以访问到我们的服务器了。
由于默认配置文件 /etc/nginx/nginx.conf
的 http 模块中有一句 include /etc/nginx/conf.d/*.conf
也就是说 conf.d
文件夹下的所有 *.conf
文件都会作为子配置项被引入配置文件中。为了维护方便,我在 /etc/nginx/conf.d
文件夹中新建一个 fe.sherlocked93.club.conf
:
# /etc/nginx/conf.d/fe.sherlocked93.club.conf
server {
listen 80;
server_name fe.sherlocked93.club;
location / {
root /usr/share/nginx/html/fe;
index index.html;
}
}
然后在 /usr/share/nginx/html
文件夹下新建 fe 文件夹,新建文件index.html
,内容随便写点,改完 nginx -s reload
重新加载,浏览器中输入fe.sherlocked93.club
,发现从二级域名就可以访问到我们刚刚新建的 fe 文件夹:
二、配置反向代理
反向代理是工作中最常用的服务器功能,经常被用来解决跨域问题,下面简单介绍一下如何实现反向代理。
首先进入 Nginx 的主配置文件:vim /etc/nginx/nginx.conf,为了看起来方便,把行号显示出来 :set nu
(个人习惯),然后我们去 http
模块的 server
块中的 location /
,增加一行将默认网址重定向到最大学习网站 Bilibili 的 proxy_pass
配置
改完保存退出,nginx -s reload
重新加载,进入默认网址,那么现在就直接跳转到 B 站了,实现了一个简单的代理。
实际使用中,可以将请求转发到本机另一个服务器上,也可以根据访问的路径跳转到不同端口的服务中。比如我们监听 9001
端口,然后把访问不同路径的请求进行反向代理:
http://127.0.0.1:9001/edu
的请求转发到 http://127.0.0.1:8080
http://127.0.0.1:9001/vod
的请求转发到 http://127.0.0.1:8081
这种要怎么配置呢,首先同样打开主配置文件,然后在 http 模块下增加一个 server 块:
server {
listen 9001;
server_name *.sherlocked93.club;
location ~ /edu/ {
proxy_pass http://127.0.0.1:8080;
}
location ~ /vod/ {
proxy_pass http://127.0.0.1:8081;
}
}
反向代理还有一些其他的指令,可以了解一下:
proxy_set_header
:在将客户端请求发送给后端服务器之前,更改来自客户端的请求头信息;proxy_connect_timeout
:配置 Nginx 与后端代理服务器尝试建立连接的超时时间;proxy_read_timeout
:配置 Nginx 向后端服务器组发出 read 请求后,等待相应的超时时间;proxy_send_timeout
:配置 Nginx 向后端服务器组发出 write 请求后,等待相应的超时时间;proxy_redirect
:用于修改后端服务器返回的响应头中的 Location 和 Refresh。三、跨域 CORS 配置
关于简单请求、非简单请求、跨域的概念,前面已经介绍过了,还不了解的可以看看前面的讲解。现在前后端分离的项目一统天下,经常本地起了前端服务,需要访问不同的后端地址,不可避免遇到跨域问题。
要解决跨域问题,我们来制造一个跨域问题。首先和前面设置二级域名的方式一样,先设置好 fe.sherlocked93.club
和 be.sherlocked93.club
二级域名,都指向本云服务器地址,虽然对应 IP 是一样的,但是在 fe.sherlocked93.club
域名发出的请求访问 be.sherlocked93.club
域名的请求还是跨域了,因为访问的 host 不一致。
1、使用反向代理解决跨域
在前端服务地址为 fe.sherlocked93.club
的页面请求 be.sherlocked93.club
的后端服务导致的跨域,可以这样配置:
server {
listen 9001;
server_name fe.sherlocked93.club;
location / {
proxy_pass be.sherlocked93.club;
}
}
这样就将对前一个域名 fe.sherlocked93.club
的请求全都代理到了 be.sherlocked93.club
,前端的请求都被我们用服务器代理到了后端地址下,绕过了跨域。
这里对静态文件的请求和后端服务的请求都以 fe.sherlocked93.club
开始,不易区分,所以为了实现对后端服务请求的统一转发,通常我们会约定对后端服务的请求加上 /apis/
前缀或者其他的 path 来和对静态资源的请求加以区分,此时我们可以这样配置:
# 请求跨域,约定代理后端服务请求path以/apis/开头
location ^~/apis/ {
# 这里重写了请求,将正则匹配中的第一个分组的path拼接到真正的请求后面,并用break停止后续匹配
rewrite ^/apis/(.*)$ /$1 break;
proxy_pass be.sherlocked93.club;
# 两个域名之间cookie的传递与回写
proxy_cookie_domain be.sherlocked93.club fe.sherlocked93.club;
}
这样,静态资源我们使用 fe.sherlocked93.club/xx.html
,动态资源我们使用 fe.sherlocked93.club/apis/getAwo
,浏览器页面看起来仍然访问的前端服务器,绕过了浏览器的同源策略,毕竟我们看起来并没有跨域。也可以统一一点,直接把前后端服务器地址直接都转发到另一个 server.sherlocked93.club
,只通过在后面添加的 path 来区分请求的是静态资源还是后端服务,看需求了。
2、配置 header 解决跨域
当浏览器在访问跨源的服务器时,也可以在跨域的服务器上直接设置 Nginx,从而前端就可以无感地开发,不用把实际上访问后端的地址改成前端服务的地址,这样可适性更高。比如前端站点是 fe.sherlocked93.club
,这个地址下的前端页面请求 be.sherlocked93.club
下的资源,就会跨域。
在 /etc/nginx/conf.d/
文件夹中新建一个配置文件,对应二级域名 be.sherlocked93.club
:
# /etc/nginx/conf.d/be.sherlocked93.club.conf
server {
listen 80;
server_name be.sherlocked93.club;
add_header ‘Access-Control-Allow-Origin‘ $http_origin; # 全局变量获得当前请求origin,带cookie的请求不支持*
add_header ‘Access-Control-Allow-Credentials‘ ‘true‘; # 为 true 可带上 cookie
add_header ‘Access-Control-Allow-Methods‘ ‘GET, POST, OPTIONS‘; # 允许请求方法
add_header ‘Access-Control-Allow-Headers‘ $http_access_control_request_headers; # 允许请求的 header,可以为 *
add_header ‘Access-Control-Expose-Headers‘ ‘Content-Length,Content-Range‘;
if ($request_method = ‘OPTIONS‘) {
add_header ‘Access-Control-Max-Age‘ 1728000; # OPTIONS 请求的有效期,在有效期内不用发出另一条预检请求
add_header ‘Content-Type‘ ‘text/plain; charset=utf-8‘;
add_header ‘Content-Length‘ 0;
return 204; # 200 也可以
}
location / {
root /usr/share/nginx/html/be;
index index.html;
}
}
四、配置 gzip
使用 gzip 不仅需要 Nginx 配置,浏览器端也需要配合,需要在请求消息头中包含 Accept-Encoding: gzip
(IE5 之后所有的浏览器都支持了,是现代浏览器的默认设置)。一般在请求 html 和 css 等静态资源的时候,支持的浏览器在 request 请求静态资源的时候,会加上 Accept-Encoding: gzip
这个 header,表示自己支持 gzip 的压缩方式,Nginx 在拿到这个请求的时候,如果有相应配置,就会返回经过 gzip 压缩过的文件给浏览器,并在 response 相应的时候加上 content-encoding: gzip
来告诉浏览器自己采用的压缩方式(因为浏览器在传给服务器的时候一般还告诉服务器自己支持好几种压缩方式),浏览器拿到压缩的文件后,根据自己的解压方式进行解析。
先来看看 Nginx 怎么进行 gzip 配置,和之前的配置一样,为了方便管理,还是在 /etc/nginx/conf.d/
文件夹中新建配置文件 gzip.conf
:
# /etc/nginx/conf.d/gzip.conf
gzip on; # 默认off,是否开启gzip
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# 上面两个开启基本就能跑起了,下面的愿意折腾就了解一下
gzip_static on;
gzip_proxied any;
gzip_vary on;
gzip_comp_level 6;
gzip_buffers 16 8k;
# gzip_min_length 1k;
gzip_http_version 1.1;
稍微解释一下:
.gz
文件内容;Vary:Accept-Encoding
,使代理服务器根据请求头中的 Accept-Encoding
识别是否启用 gzip 压缩;Content-Length
中进行获取。默认值是 0,不管页面多大都压缩。建议设置成大于 1k 的字节数,小于 1k 可能会越压越大; 这个配置可以插入到 http 模块整个服务器的配置里,也可以插入到需要使用的虚拟主机的 server
或者下面的 location
模块中,当然像上面我们这样写的话就是被 include 到 http 模块中了。
其他更全的配置信息可以查看 <官网文档ngx_http_gzip_module>
注意了,一般 gzip 的配置建议加上 gzip_min_length 1k
,不加的话:
由于文件太小,gzip 压缩之后得到了 -48% 的体积优化,压缩之后体积还比压缩之前体积大了,所以最好设置低于 1kb
的文件就不要 gzip 压缩了
1、Webpack 的 gzip 配置
当前端项目使用 Webpack 进行打包的时候,也可以开启 gzip 压缩:
// vue-cli3 的 vue.config.js 文件
const CompressionWebpackPlugin = require(‘compression-webpack-plugin‘)
module.exports = {
// gzip 配置
configureWebpack: config => {
if (process.env.NODE_ENV === ‘production‘) {
// 生产环境
return {
plugins: [new CompressionWebpackPlugin({
test: /\.js$|\.html$|\.css/, // 匹配文件名
threshold: 10240, // 文件压缩阈值,对超过10k的进行压缩
deleteOriginalAssets: false // 是否删除源文件
})]
}
}
},
...
}
可以看到某些打包之后的文件下面有一个对应的 .gz
经过 gzip
压缩之后的文件,这是因为这个文件超过了 10kb
,有的文件没有超过 10kb
就没有进行 gzip
打包,如果你期望压缩文件的体积阈值小一点,可以在 compression-webpack-plugin
这个插件的配置里进行对应配置。
那么为啥这里 Nginx 已经有了 gzip 压缩,Webpack 这里又整了个 gzip 呢,因为如果全都是使用 Nginx 来压缩文件,会耗费服务器的计算资源,如果服务器的 gzip_comp_level
配置的比较高,就更增加服务器的开销,相应增加客户端的请求时间,得不偿失。
如果压缩的动作在前端打包的时候就做了,把打包之后的高压缩等级文件作为静态资源放在服务器上,Nginx 会优先查找这些压缩之后的文件返回给客户端,相当于把压缩文件的动作从 Nginx 提前给 Webpack 打包的时候完成,节约了服务器资源,所以一般推介在生产环境应用 Webpack 配置 gzip 压缩。
五、配置负载均衡
负载均衡在之前已经介绍了相关概念了,主要思想就是把负载均匀合理地分发到多个服务器上,实现压力分流的目的。主要配置如下:
http {
upstream myserver {
# ip_hash; # ip_hash 方式
# fair; # fair 方式
server 127.0.0.1:8081; # 负载均衡目的服务地址
server 127.0.0.1:8080;
server 127.0.0.1:8082 weight=10; # weight 方式,不写默认为 1
}
server {
location / {
proxy_pass http://myserver;
proxy_connect_timeout 10;
}
}
}
Nginx 提供了好几种分配方式,默认为轮询,就是轮流来。有以下几种分配方式:
六、配置动静分离
动静分离在之前也介绍过了,就是把动态和静态的请求分开。方式主要有两种,一种是纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案。另外一种方法就是动态跟静态文件混合在一起发布, 通过 Nginx 配置来分开。
通过 location 指定不同的后缀名实现不同的请求转发。通过 expires 参数设置,可以使浏览器缓存过期时间,减少与服务器之前的请求和流量。具体 expires 定义:是给一个资源设定一个过期时间,也就是说无需去服务端验证,直接通过浏览器自身确认是否过期即可,所以不会产生额外的流量。此种方法非常适合不经常变动的资源。(如果经常更新的文件,不建议使用 expires 来缓存),我这里设置 3d,表示在这 3 天之内访问这个URL,发送一个请求,比对服务器该文件最后更新时间没有变化。则不会从服务器抓取,返回状态码 304,如果有修改,则直接从服务器重新下载,返回状态码 200。
server {
location /www/ {
root /data/;
index index.html index.htm;
}
location /image/ {
root /data/;
autoindex on;
}
}
七、配置高可用集群(双机热备)
当主 Nginx 服务器宕机之后,切换到备份 Nginx 服务器
首先安装 keepalived,yum install keepalived -y
然后编辑 /etc/keepalived/keepalived.conf
配置文件,并在配置文件中增加 vrrp_script
定义一个外围检测机制,并在 vrrp_instance
中通过定义 track_script
来追踪脚本执行过程,实现节点转移:
global_defs{
notification_email {
acassen@firewall.loc
}
notification_email_from Alexandre@firewall.loc
smtp_server 127.0.0.1
smtp_connect_timeout 30 // 上面都是邮件配置,没卵用
router_id LVS_DEVEL // 当前服务器名字,用hostname命令来查看
}
vrrp_script chk_maintainace { // 检测机制的脚本名称为chk_maintainace
script "[[ -e/etc/keepalived/down ]] && exit 1 || exit 0" // 可以是脚本路径或脚本命令
// script "/etc/keepalived/nginx_check.sh" // 比如这样的脚本路径
interval 2 // 每隔2秒检测一次
weight -20 // 当脚本执行成立,那么把当前服务器优先级改为-20
}
vrrp_instanceVI_1 { // 每一个vrrp_instance就是定义一个虚拟路由器
state MASTER // 主机为MASTER,备用机为BACKUP
interface eth0 // 网卡名字,可以从ifconfig中查找
virtual_router_id 51 // 虚拟路由的id号,一般小于255,主备机id需要一样
priority 100 // 优先级,master的优先级比backup的大
advert_int 1 // 默认心跳间隔
authentication { // 认证机制
auth_type PASS
auth_pass 1111 // 密码
}
virtual_ipaddress { // 虚拟地址vip
172.16.2.8
}
}
其中检测脚本 nginx_check.sh
,这里提供一个
#!/bin/bash
A=`ps -C nginx --no-header | wc -l`
if [ $A -eq 0 ];then
/usr/sbin/nginx # 尝试重新启动nginx
sleep 2 # 睡眠2秒
if [ `ps -C nginx --no-header | wc -l` -eq 0 ];then
killall keepalived # 启动失败,将keepalived服务杀死。将vip漂移到其它备份节点
fi
fi
复制一份到备份服务器,备份 Nginx 的配置要将 state
后改为 BACKUP
,priority
改为比主机小。
设置完毕后各自 service keepalived start
启动,经过访问成功之后,可以把 Master 机的 keepalived 停掉,此时 Master 机就不再是主机了 service keepalived stop
,看访问虚拟 IP 时是否能够自动切换到备机 ip addr
。再次启动 Master 的 keepalived,此时 vip 又变到了主机上。
八、适配 PC 或移动设备
根据用户设备不同返回不同样式的站点,以前经常使用的是纯前端的自适应布局,但无论是复杂性和易用性上面还是不如分开编写的好,比如我们常见的淘宝、京东......这些大型网站就都没有采用自适应,而是用分开制作的方式,根据用户请求的 user-agent
来判断是返回 PC 还是 H5 站点。
首先在 /usr/share/nginx/html
文件夹下 mkdir
分别新建两个文件夹 PC
和 mobile
,vim
编辑两个 index.html
随便写点内容。
然后和设置二级域名虚拟主机时候一样,去 /etc/nginx/conf.d
文件夹下新建一个配置文件 fe.sherlocked93.club.conf
:
# /etc/nginx/conf.d/fe.sherlocked93.club.conf
server {
listen 80;
server_name fe.sherlocked93.club;
location / {
root /usr/share/nginx/html/pc;
if ($http_user_agent ~* ‘(Android|webOS|iPhone|iPod|BlackBerry)‘) {
root /usr/share/nginx/html/mobile;
}
index index.html;
}
}
配置基本没什么不一样的,主要多了一个 if
语句,然后使用$http_user_agent
全局变量来判断用户请求的 user-agent
,指向不同的 root 路径,返回对应站点。
九、配置 HTTPS
具体配置过程网上挺多的了,也可以使用你购买的某某云,一般都会有免费申请的服务器证书,安装直接看所在云的操作指南即可。
我购买的腾讯云提供的亚洲诚信机构颁发的免费证书只能一个域名使用,二级域名什么的需要另外申请,但是申请审批比较快,一般几分钟就能成功,然后下载证书的压缩文件,里面有个 nginx 文件夹,把 xxx.crt
和 xxx.key
文件拷贝到服务器目录,再配置下:
server {
listen 443 ssl http2 default_server; # SSL 访问端口号为 443
server_name sherlocked93.club; # 填写绑定证书的域名
ssl_certificate /etc/nginx/https/1_sherlocked93.club_bundle.crt; # 证书文件地址
ssl_certificate_key /etc/nginx/https/2_sherlocked93.club.key; # 私钥文件地址
ssl_session_timeout 10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #请按照以下协议配置
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
写完 nginx -t -q
校验一下,没问题就 nginx -s reload
,现在去访问 https://sherlocked93.club/
就能访问 HTTPS 版的网站了。一般还可以加上几个增强安全性的命令:
add_header X-Frame-Options DENY; # 减少点击劫持
add_header X-Content-Type-Options nosniff; # 禁止服务器自动解析资源类型
add_header X-Xss-Protection 1; # 防XSS攻击
十、常用技巧
1、静态服务
server {
listen 80;
server_name static.sherlocked93.club;
charset utf-8; # 防止中文文件名乱码
location /download {
alias /usr/share/nginx/html/static; # 静态资源目录
autoindex on; # 开启静态资源列目录
autoindex_exact_size off; # on(默认)显示文件的确切大小,单位是byte;off显示文件大概大小,单位KB、MB、GB
autoindex_localtime off; # off(默认)时显示的文件时间为GMT时间;on显示的文件时间为服务器时间
}
}
2、图片防盗链
server {
listen 80;
server_name *.sherlocked93.club;
# 图片防盗链
location ~* \.(gif|jpg|jpeg|png|bmp|swf)$ {
valid_referers none blocked 192.168.0.2; # 只允许本机 IP 外链引用
if ($invalid_referer){
return 403;
}
}
}
3、请求过滤
# 非指定请求全返回 403
if ( $request_method !~ ^(GET|POST|HEAD)$ ) {
return 403;
}
location / {
# IP访问限制(只允许IP是 192.168.0.2 机器访问)
allow 192.168.0.2;
deny all;
root html;
index index.html index.htm;
}
4、配置图片、字体等静态文件缓存
由于图片、字体、音频、视频等静态文件在打包的时候通常会增加了 hash,所以缓存可以设置的长一点,先设置强制缓存,再设置协商缓存;如果存在没有 hash 值的静态文件,建议不设置强制缓存,仅通过协商缓存判断是否需要使用缓存。
# 图片缓存时间设置
location ~ .*\.(css|js|jpg|png|gif|swf|woff|woff2|eot|svg|ttf|otf|mp3|m4a|aac|txt)$ {
expires 10d;
}
# 如果不希望缓存
expires -1;
5、单页面项目 history 路由配置
server {
listen 80;
server_name fe.sherlocked93.club;
location / {
root /usr/share/nginx/html/dist; # vue 打包后的文件夹
index index.html index.htm;
try_files $uri $uri/ /index.html @rewrites;
expires -1; # 首页一般没有强制缓存
add_header Cache-Control no-cache;
}
# 接口转发,如果需要的话
#location ~ ^/api {
# proxy_pass http://be.sherlocked93.club;
#}
location @rewrites {
rewrite ^(.+)$ /index.html break;
}
}
6、HTTP 请求转发到 HTTPS
配置完 HTTPS 后,浏览器还是可以访问 HTTP 的地址http://sherlocked93.club/
的,可以做一个 301 跳转,把对应域名的 HTTP 请求重定向到 HTTPS 上
server {
listen 80;
server_name www.sherlocked93.club;
# 单域名重定向
if ($host = ‘www.sherlocked93.club‘){
return 301 https://www.sherlocked93.club$request_uri;
}
# 全局非 https 协议时重定向
if ($scheme != ‘https‘) {
return 301 https://$server_name$request_uri;
}
# 或者全部重定向
return 301 https://$server_name$request_uri;
# 以上配置选择自己需要的即可,不用全部加
}
7、泛域名路径分离
这是一个非常实用的技能,经常有时候我们可能需要配置一些二级或者三级域名,希望通过 Nginx 自动指向对应目录,比如:
test1.doc.sherlocked93.club
自动指向 /usr/share/nginx/html/doc/test1
服务器地址;test2.doc.sherlocked93.club
自动指向 /usr/share/nginx/html/doc/test2
服务器地址;server {
listen 80;
server_name ~^([\w-]+)\.doc\.sherlocked93\.club$;
root /usr/share/nginx/html/doc/$1;
}
8、泛域名转发
有时候我们希望把二级或者三级域名链接重写到我们希望的路径,让后端就可以根据路由解析不同的规则:
test1.serv.sherlocked93.club/api?name=a
自动转发到 127.0.0.1:8080/test1/api?name=a
;test2.serv.sherlocked93.club/api?name=a
自动转发到 127.0.0.1:8080/test2/api?name=a
;server {
listen 80;
server_name ~^([\w-]+)\.serv\.sherlocked93\.club$;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:8080/$1$request_uri;
}
}
原文:https://www.cnblogs.com/goloving/p/12879676.html