Ari的小跟班

  :: :: 博问 :: 闪存 :: :: :: :: 管理 ::
  65 随笔 :: 1 文章 :: 1 评论 :: 14948 阅读

参考Nginx学习 | 何叨叨的个人博客 (heyingjiee.github.io)尚硅谷Nginx教程-bilibili,感谢作者和尚硅谷。

Nginx介绍

​ 虚拟机安装就略过了。

  • Nginx开源版 http://nginx.org/en/

    官方原始的Nginx版本

  • Nginx plus商业版

    开箱即用,集成了大量功能

  • Open Resty https://openresty.org/cn/

    OpenResty是一个基于Nginx与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。更适用于需要大量二次开发的场景,有极强的扩展性

  • Tengine https://tengine.taobao.org/

    由淘宝网发起的Web服务器项目。它在Nginx 的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网 天猫商城 等得到了很好的检验。相比于Open Resty,扩展性不够强,但是能够满足绝多数使用场景

Nginx安装

​ 下载Nginx官方安装包http://nginx.org/en/download.html

1.解压安装包

​ 上传到虚拟机目录里,我将安装包解压到了/usr/software/下,使用命令tar -zxvf进行解压,得到/usr/software/nginx-1.23.3

2.安装依赖库

#安装C编译器
yum install -y gcc
#安装pcre库
yum install -y pcre pcre-devel
#安装zlib
yum install -y zlib zlib-devel

3.安装

./configure --prefix=/usr/local/nginx #使用prefix选项指定安装的目录
make
make install

4.启动

cd /usr/local/nginx/sbin
ls # 里面是一个nginx的可执行文件
./nginx # 启动这个可执行

5.关闭防火墙

systemctl stop firewalld

6.补充Nginx命令

./nginx -s stop #快速停止
./nginx -s quit #完成已接受的请求后,停止
./nginx -s reload #重新加载配置
./nginx -t #检查nginx配置是否正确

7.查看nginx状态

ps -ef | grep nginx

启动时:

​ 可以看到master进程和worker进程都存在。如果nginx处在停止状态,则只会有最下面一个的进程,masterworker进程都不会存在。

8.注册系统服务,通过系统服务的方式启动nginx

(1)创建服务脚本:vim /usr/lib/systemd/system/nginx.service

(2)其中的内容为:

​ 如果安装的目录不是在/usr/local/nginx下的话,需要修改目录地址。

[Unit]
Description=nginx
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
ExecQuit=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true
[Install]
WantedBy=multi-user.target # 多用户

(3)重新加载系统服务:systemctl daemon-reload

​ 之后启动nginx服务就可以使用systemctl start nginx,我们可以用systemctl status nginx查看nginx状态。

​ 设置成开机启动,使用命令systemctl enable nginx.service

Nginx目录

​ Nginx一般安装在/usr/local/nginx目录下(安装时--prefix可指定安装目录),目录结构如下。

conf #配置文件
|-nginx.conf # 主配置文件
|-其他配置文件 # 可通过那个include关键字,引入到了nginx.conf生效
html #静态页面
logs
|-access.log #访问日志(每次访问都会记录)
|-error.log #错误日志
|-nginx.pid #进程号,会标记出当前nginx进程的进程号
sbin
|-nginx #主进程文件
*_temp #运行时,生成临时文件

Nginx运行流程

1.首先启动/sbin/nginx进程,开启master进程。

2.master进程会读取并校验配置文件,检查配置文件是否正确。

3.启动worker子进程,此时worker已经获取到了配置文件(conf文件)

4.请求过来之后,worker会根据请求的路径以及配置文件去找对应的响应信息。

​ worker是进程,会有多个,master进程只有一个用于协调各个worker之间的工作。

Nginx配置文件

​ 后面学习Nginx配置,每次修改配置文件,一定要重载才能生效。systemctl reload nginx

​ 将配置文件的注释部分去掉之后,配置文件如下所示:

worker_processes 1; # 启动的worker进程数
events {
worker_connections 1024; #每个worker进程的连接数
}
http {
include mime.types; #include是引入关键字,这里引入了mime.types这个配置文件(同在conf目录下,mime.types是用来定义,请求返回的content-type)
default_type application/octet-stream; #mime.types未定义的,使用默认格式application/octet-stream
sendfile on; #详情,见下文
keepalive_timeout 65; #长链接超时时间
#一个nginx可以启用多个server(虚拟服务器 vhost),每个server就是一个主机
server {
listen 80;#监听端口80
server_name localhost; #接收的域名 或者 主机名
location / {
root html; #根目录指向html目录
index index.html index.htm; #域名/index 指向 index.html index.htm文件
}
error_page 500 502 503 504 /50x.html; # 服务器错误码为500 502 503 504,转到"域名/50x.html"
location = /50x.html {# 指定到html文件夹下找/50x.htm
root html;
}
}
}

核心配置

1.worker_processes:启动的worker子进程的数量,基本是对应到CPU物理的内核数量。

2.events

3.http

(1)include表示引入文件,这里引入了同目录下的mime.types配置文件,其内容为:

types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
application/javascript js;
application/atom+xml atom;
application/rss+xml rss;
text/mathml mml;
text/plain txt;
text/vnd.sun.j2me.app-descriptor jad;
text/vnd.wap.wml wml;
text/x-component htc;
image/avif avif;
image/png png;
image/svg+xml svg svgz;
image/tiff tif tiff;
image/vnd.wap.wbmp wbmp;
image/webp webp;
image/x-icon ico;
image/x-jng jng;
image/x-ms-bmp bmp;
font/woff woff;
font/woff2 woff2;
application/java-archive jar war ear;
application/json json;
application/mac-binhex40 hqx;
application/msword doc;
application/pdf pdf;
application/postscript ps eps ai;
application/rtf rtf;
application/vnd.apple.mpegurl m3u8;
application/vnd.google-earth.kml+xml kml;
application/vnd.google-earth.kmz kmz;
application/vnd.ms-excel xls;
application/vnd.ms-fontobject eot;
application/vnd.ms-powerpoint ppt;
application/vnd.oasis.opendocument.graphics odg;
application/vnd.oasis.opendocument.presentation odp;
application/vnd.oasis.opendocument.spreadsheet ods;
application/vnd.oasis.opendocument.text odt;
application/vnd.openxmlformats-officedocument.presentationml.presentation
pptx;
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
xlsx;
application/vnd.openxmlformats-officedocument.wordprocessingml.document
docx;
application/vnd.wap.wmlc wmlc;
application/wasm wasm;
application/x-7z-compressed 7z;
application/x-cocoa cco;
application/x-java-archive-diff jardiff;
application/x-java-jnlp-file jnlp;
application/x-makeself run;
application/x-perl pl pm;
application/x-pilot prc pdb;
application/x-rar-compressed rar;
application/x-redhat-package-manager rpm;
application/x-sea sea;
application/x-shockwave-flash swf;
application/x-stuffit sit;
application/x-tcl tcl tk;
application/x-x509-ca-cert der pem crt;
application/x-xpinstall xpi;
application/xhtml+xml xhtml;
application/xspf+xml xspf;
application/zip zip;
application/octet-stream bin exe dll;
application/octet-stream deb;
application/octet-stream dmg;
application/octet-stream iso img;
application/octet-stream msi msp msm;
audio/midi mid midi kar;
audio/mpeg mp3;
audio/ogg ogg;
audio/x-m4a m4a;
audio/x-realaudio ra;
video/3gpp 3gpp 3gp;
video/mp2t ts;
video/mp4 mp4;
video/mpeg mpeg mpg;
video/quicktime mov;
video/webm webm;
video/x-flv flv;
video/x-m4v m4v;
video/x-mng mng;
video/x-ms-asf asx asf;
video/x-ms-wmv wmv;
video/x-msvideo avi;
}

​ 对应的分别是类型以及文件后缀名。default_type application/octet-stream; mime.types未定义的,使用默认格式application/octet-stream,即以数据流的方式进行下载,比如exe文件,浏览器是无法加载exe文件的,这个时候就会显示下载。

(2)snedfile表示数据零拷贝,打开sendfile,用户请求的数据不用再加载到nginx的内存中,而是直接发送

​ 若没有开启零拷贝,则是会先拷贝到nginx应用程序的内存中:

​ nginx将文件读到自己的应用程序内存后,再从自己的应用程序内存里读取文件到网络接口缓存,再由OS调度读取网络接口缓存从而返回给用户。


​ 若开启了零拷贝,则流程为:

​ nginx直接发送一个带有套接字或者文件地址的信号sendfile()给系统内核,系统内核直接读取文件到网络接口缓存中后返回给用户。

虚拟主机

​ 一台主机可以绑定多个域名,这样可以节省服务器资源,nginx可以根据域名来区分访问的内容,从而到对应的文件夹中寻找响应文件。

​ 为了模拟域名的效果,我们可以先修改本机host,写一些域名绑定到虚拟机上:

​ 为了模拟出多站点的情况,我们可以先创建对应的文件夹,比如在根目录下创建/www文件夹,其下再创建vod和www文件夹来模拟多站点的情况,每个单独的文件夹下都有一个index.html:

​ 接下来编辑nginx的配置文件(nginx自己有一个nginx.conf.default文件,如果有写错了的情况,可以用默认的配置文件代替):

worker_processes 1; # 启动的worker进程数
events {
worker_connections 1024; #每个worker进程的连接数
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
#一个nginx可以启用多个server(虚拟服务器 vhost),每个server就是一个主机
server {
listen 80;#监听端口80
server_name localhost;
location / {
root /www/www;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {# 指定到html文件夹下找/50x.htm
root html;
}
}
server {
listen 88;#监听端口88
server_name localhost;
location / {
root /www/vod;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {# 指定到html文件夹下找/50x.htm
root html;
}
}
}

​ 比如80端口监听主站点的,88端口监听的是vod站点的。

​ 修改配置文件后需要reload一下:systemctl reload nginx

​ 那假如说我想都用80端口,根据域名来区分返回的内容,只需要把server_name改成对应的域名即可,总之只要保证每个server的listen(端口号)+server_name(域名)保持唯一性即可。

多个域名配置到同一个文件夹

​ 可以在server_name后面加上多个域名,每个域名、主机名之间用空格区分开来。比如server_name vod1.test.com vod2.test.com;,比如这个配置就是将两个域名都配置到一个文件夹下了。

server {
listen 80;#监听端口80
server_name vod1.test.com vod2.test.com;
location / {
root /www/www;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {# 指定到html文件夹下找/50x.htm
root html;
}
}

​ 除了配置固定的主机名外,还可以使用通配符的方式进行配置,比如*.test.comwww.test.*,这个可以查看专门的文档

反向代理

​ 反向代理的概念非常简单,用户访问反向代理服务器(nginx)后,把请求转发给对应的业务服务器,随后业务服务器返回结果给nginx,nginx将结果再返回给用户,这是一种典型的隧道式代理,隧道式服务器中,用户与业务服务器不能直接产生连接。

​ 因为隧道式代理非常考验nginx的能力,所以又提出了一种LVS的代理模式,与隧道式的区别在于,nginx转发请求给业务服务器后,业务服务器直接返回结果给用户,即返回结果的时候不再经过nginx。LVS代理模式中,业务服务器只接受从nginx进入的流量,但是发出数据时不受限制,可以发给任意的一个用户。

​ 反向代理的实现方式使用proxy_pass实现,使用了proxy_pass后,rootindex就不需要再配置了。

server {
listen 80;#监听端口80
server_name localhost;
location / {
proxy_pass http://www.atguigu.com;
#root /www/www;
#index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {# 指定到html文件夹下找/50x.htm
root html;
}
}

​ 将本机反向代理至http://www.atguigu.com,这个时候访问本机地址192.168.247.128时,就会转到尚硅谷的主页并且地址栏不会变化。

​ 不过反向代理是不支持反向代理至https的,不过服务端一般都会对http请求进行重定向至https,所以这个问题不大。

负载均衡

​ 刚刚我们提到nginx作为反向代理服务器时转发请求给对应的业务服务器,这个过程中,nginx可以做负载均衡的功能。负载均衡:把请求,按照一定算法规则,分配给多台业务服务器(即使其中一个坏了/维护升级,还有其他服务器可以继续提供服务)

轮询

​ 负载均衡的配置要与proxy_pass配置项搭配的使用,我们可以定义一个地址别名,随后使用upstream来配置这个别名的负载均衡。

http{
upstream httpds{
server 192.168.174.133:80; #如果是80端口,可以省略不写
server 192.168.174.134:80;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://httpds;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}

​ 使用upstream定义一组地址【在server字段下】,访问localhost,访问都会代理到192.168.174.133:80192.168.174.134:80这两个地址之一,每次访问这两个地址轮着切换(后面讲到,因为默认权重相等)。

设置权重

​ 访问使用哪个地址的权重

upstream httpds{
server 192.168.174.133:80 weight=10;
server 192.168.174.134:80 weight=80;
}

​ 设置down后,可以让这台机器不参与负载均衡,也就是休息。(使用不多)

upstream httpds{
server 192.168.174.133:80 weight=10 down;
server 192.168.174.134:80 weight=80;
}

​ 备用服务器,如果192.168.174.133:80出现故障,无法提供服务,就用使用backup的这个机器。(使用不多)

upstream httpds{
server 192.168.174.133:80 weight=10;
server 192.168.174.134:80 weight=80 backup;
}

动静分离

​ 当用户请求时,动态请求分配到Tomcat业务服务器,静态资源请求放在Nginx服务器中。可用于中小型的应用。

例子:

  • 如果请求的资源地址是location//的优先级比较低,如果下面的location没匹配到,就会走http://xxx这个地址的机器
  • 如果请求的资源地址是location/css/*,就会被匹配到nginx的html目录下的css文件夹中(我们把css静态资源放在这个位置)
server {
listen 80;
server_name localhost;
location / { # /的优先级比较低,如果下面的location没匹配到,就会走http://xxx这个地址的机器
proxy_pass http://xxx;
}
location /css { # root指的是html,location/css指的是root下的css,所以地址就是html/css
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

​ 还可以使用正则表达式来进行匹配,这样把/js/css以及/img的请求都进行了反向代理。~表示开始正则,*表示任意字符。

location ~*/(js|css|img){
root html;
index index.html index.htm;
}

不过现在项目基本上都是前后端分离了,前端部署到nginx上,后端再另外启动一个服务。

URLRewrite

​ 这个配置在前后端分离中可能是会用到的。rewrite是URL重写的关键指令,根据regex(正则表达式)部分内容,重定向到replacement,结尾是flag标记。

rewrite <regex> <replacement> [flag];
关键字 正则 替代内容 flagt标记
正则:使用正则表达式语句进行规则匹配
替代内容:将正则匹配的内容替换成replacement
flag标记说明:
last #本条规则匹配完成后,继续向下匹配新的1ocation URI规则
break #本条规则匹配完成即终止,不再匹配后面的任何规则
redirect #返回302临重定向,游览器地址会显示跳转后的URL地址
permanent #返回301永久重定向,测览器地址栏会显示跳转后的URL地址

​ 浏览器地址栏访问 xxx/123.html实际上是访问xxx/index.jsp?pageNum=123

server {
listen 80;
server_name localhost;
location / {
rewrite ^/([0-9]+).html$ /index.jsp?pageNum=$1 break;
proxy_pass http://xxx;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

网关服务器配置

​ 上图中,应用服务器,不能直接被外网访问到,只能通过Nginx服务器进行访问(使用proxy_pass),这时候这台Nginx服务器就成为了网关服务器(承担入口的功能)

​ 所以,我们启动应用服务器的防火墙,设置其只能接受这台Nginx服务器的请求

添加rich规则

firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.174.135" port protocol="tcp" port="8080" accept"
#这里的192.168.174.135是网关 服务器地址

移除rich规则

firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="192.168.174.135" port port="8080" protocol="tcp" accept"

​ 移除和添加规则后都要重启才能生效:firewall-cmd --reload;可以使用该命令查看所有规则:firewall-cmd --list-all

防盗链

​ 当我们请求到一个页面后,这个页面一般会再去请求其中的静态资源,这时候请求头中,会有一个refer字段,表示当前这个请求的来源,我们可以限制指定来源的请求才返回,否则就不返回,这样可以节省资源。

​ 我们可以通过valid_referers none|server_name,设置有效的refer值。

  • none:检测地址没有refer,则有效;比如直接请求图片的时候(即不是在另一个页面里请求图片的情况),配置示例:valid_referes none 192.168.44.101,这种情况下资源只允许来自192.168.44.101的页面引用或者直接请求该页面。
  • server_name:检测主机地址,refer显示是从这个地址来的,则有效(server_name必须是完整的http://xxxx

注意:if ($invalid_referer)中if后有个空格,不写就会报错,报错信息如下:

nginx: [emerg] unknown directive "if($invalid_referer)" in /usr/local/nginx/conf/nginx.conf:27

​ 例子:这里设置nginx服务器中的img目录下的图片必须refer为http:192.168.174/133才能访问。

server {
listen 80;
server_name localhost;
location / {
proxy_pass http://xxx;
}
location /img{
valid_referers http:192.168.174/133;
if ($invalid_referer){#无效的
return 403;#返回状态码403
}
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

​ 如果引用这张图片的页面且refer并没有被设置,图片无法加载出来。如果直接访问图片地址,因为没有refer字段指向来源,会直接显示Nginx的页面:

设置盗链图片

​ 将提示图片放在html/img/x.png,访问设置防盗链图片时,就返回这x.png张图,if(之间必须有一个空格。

location /img{
valid_referers http:192.168.174/133;
if ($invalid_referer){#无效的
rewrite ^/ /img/x.png break;
}
root html;
index index.html index.htm;
}

高可用(High Availablity)

​ 我们之前用到的nginx的负载均衡,考虑到的场景是后端服务器如果挂掉的话,把请求转发到正常运作的服务器上,但是设想一个场景:如果nginx挂掉了,那么就没办法把请求转发给后端服务器了,自然也没法儿进行负载均衡了。

​ 那我们拓展一下,在nginx前面再放一层nginx,第一层nginx对第二层nginx做负载均衡,但是这样就会陷入到逻辑怪圈中,万一第一层nginx挂了,那第二层的nginx也访问不到了,自然也访问不到后面的应用服务器了。这个时候我们就提出了高可用的概念。

​ 用户访问时,访问的是一个虚拟IP,keepalived会选定一个主服务器使用这个虚拟IP。

​ 每台机器上的keepalived会相互通信,根据其他机器上的keepalived进程是否存在,判断服务器状态,如果默认的Master停止了,就会在剩下的Backup机器中,竞选出一台Nginx服务器作为Master

安装keepalived

​ 通过yum命令安装:

yum install -y keepalived

​ yum安装后的配置文件在/etc/keepalived/keepalived.confvrrp_instanceauthenticationvirtual_router_idvirtual_ipaddress这几个一样的机器,才算是同一个组里。这个组才会选出一个作为Master机器。

​ 这里我们设置两台机器,分别下载好keepalived,然后进行配置

机器一:

! Configuration File for keepalived
global_defs {
router_id lb1 # 名字与其他配置了keepalive的机器不重复就行
}
vrrp_instance heyingjie {#vrrp实例名可以随意取
state MASTER #只能有一个默认的Master,其他写BACKUP
interface ens33 # ip addr查看下网卡名,默认时ens33
virtual_router_id 51
priority 100 # 多台安装了keepalived的机器竞争成为Master的优先级
advert_int 1 #通信时间
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.200.16 #虚拟IP
}
}

机器二:

! Configuration File for keepalived
global_defs {
router_id lb2
}
vrrp_instance heyingjie {
state BACKUP #只能有一个默认的Master,其他写BACKUP
interface ens33
virtual_router_id 51
priority 50
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.200.16 #虚拟IP
}
}

​ 通过命令ip addr查看机器一的ip信息,可以看到虚拟IP

posted on   Ari的小跟班  阅读(276)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示