一、Nginx初识
1.1 什么是Nginx?
Nginx 是一个 http 服务器。是一个使用c语言开发的高性能的http服务器及反向代理服务器。Nginx是一款高性能的 http 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。由俄罗斯的程序设计师Igor Sysoev所开发,官方测试nginx能够支支撑5万并发链接,并且cpu、内存等资源消耗却非常低,运行非常稳定。
1.2 为什么要使用Nginx?
在传统的 Web 项目开发中,当并发量较小的情况下,我们可以直接使用一台服务器,例如:Tomcat,此时用户可以直接访问到 Tomcat 服务器,服务器直接返回数据给用户。
当然,当并发量多了之后,我们可以使用负载均衡,也就是使用多台后端服务器,当用户访问的时候,我们可以将请求提交到空闲的 Tomcat 服务器上。所以,此时我们需要使用一个中间人来帮我们完成将请求分发到不同服务器上的任务。这个中间人就是一个代理服务器 Nginx。
1.3 正向代理
什么是正向代理呢?举一个很简单的例子,如果我们需要去访问外国的网站,如果直接去请求国外的服务器的话会被他们的防火墙拦截,此时我们有两种方式实现,第一种当然就是VPN
直接翻墙,当然这是不可取的。第二种就是我们需要依靠一个代理服务器帮我们完成转发,我们中国大陆的某些服务器不能直接访问国外的某些网站是因为我们没有权限,但是向某些公司或台湾的某些地区,他们是有权访问的。我们可以先去找到这些代理服务器,让他们帮我们进行一次转发。
也就是说,正向代理是我们客户端主动去访问代理服务器,让其进行转发的过程。
1.4 反向代理
反向代理相比于正向代理更加的透明,客户端在不知情的情况下访问代理服务器进行转发的过程就是反向代理。这样一来客户端的操作更为简单,在客户端,我们只需要直接去输入网址去访问我们想要访问的网站,客户端就能够直接看到内容。当然这中间经过了代理服务器,只是客户端无感知。也就是说,其实客户端访问的内容都是访问的代理服务器,然后代理服务器来决定将请求分发到后端的哪一台服务器上。当服务器完成操作后将数据交给代理服务器,再由代理服务器去将这个数据返回给客户端。
也就是说,反向代理是在客户端不知情的情况下被动访问代理服务器的过程。
二、Nginx基础命令
2.1 启动和关闭Nginx
在我们的 Linux 安装目录下,将Nginx安装到了/usr/local/nginx
,此时我们进入这个目录,然后直接使用./nginx
命令来启动即可
启动完成之后可以通过ps aux | grep "nginx"
来验证是否正常启动。
然后我们查询虚拟电脑的 IP 地址,ip addr
或者使用ifconfig
(需要安装)
在浏览器输入 IP 即可访问到 Nginx 的主页。
我们也可以使用./nginx -s stop
来停止 Nginx 进程。
在 Nginx 启动后会将 Nginx 启动的 PID 存放在当前目录下的nginx.pid
文件中,使用cat
命令来查看文件中的内容
cat ./nginx.pid
我们也可以使用kill 参数 PID
命令来杀死进程
kill -9 PID
强制停止服务kill -TERM PID
快速停止服务-
2.2 信号处理命令
./nginx -s (stop/quit/reopen/reload)
等信号处理命令 stop
快速停止服务quit
缓慢停止服务reopen
重新打开reload
重新加载,在更改配置后使用三、配置
Nginx 的配置总共分为三个部分,分别是全局块、events
块、http
块3.1 全局块
在全局块中可以配置全局指令、指定运行时用户组、指定进程id存放位置、日志存放位置、以及指定worker process
数量等。配置文件预览: ```nginx配置用户或用户组
user nobody;
允许生成的进程数
worker_processes 1;
日志路径设置,可以设置日志级别
error_log logs/error.log;
error_log logs/error.log notice;
error_log logs/error.log info;
存储进程id的文件地址
pid logs/nginx.pid;
<a name="poKfb"></a>
## 3.2 events块
`events`块中可以配置影响 Nginx 服务器和用户网络连接的配置,例如:每个进程的最大连接数、选取哪种事件驱动模型,以及在网络连接过程中,是否开启多个、是否序列化等。
```nginx
events {
# 每个进程的最大连接数
worker_connections 1024;
}
3.3 http块
http
块是可以配置代理、缓存、日志等绝大多数地方,可以嵌套多个server
块,而不同的server
可以对应不同的域名(虚拟主机)。
3.3.1 虚拟主机的配置
虚拟主机:同一台 Nginx 服务器,可以支持多个网站的运行,每个虚拟主机之间都相互独立,具有完整功能。
http {
# 对应虚拟主机的配置
server{
# 监听端口
listen 80;
# 监听域名
server_name localhost;
# 定位出路径或文件地址
location / {
# 相对路径
root html;
# 默认跳转的首页地址
index index.html index.htm;
}
}
server{
# .....
}
}
3.3.2 案例:配置指定域名访问到Nginx上的页面
首先,我们在安装目录下创建一个文件夹,来存放我们的页面
mkdir oceanspace123
然后在其中编写一个index.html
文件
# 进入此目录
cd oceanspace123
# 编写index.html
vim index.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html"; charset="UTF-8" />
<title>Welcome Ocean Nginx</title>
</head>
<body>
<h1 style="text-align:center" >Hello Ocean,Welcome to Nginx!!</h1>
</body>
</html>
更改nginx.conf
配置
http {
# 对应虚拟主机的配置
server{
# 监听端口
listen 80;
# 监听域名
server_name oceanspace.top;
# 定位出路径或文件地址
location / {
# 相对路径
root oceanspace123;
# 默认跳转的首页地址
index index.html;
}
}
}
给域名配置 IP 地址映射,需要更改hosts
文件,路径:C:\Windows\System32\drivers\etc
# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
# 102.54.94.97 rhino.acme.com # source server
# 38.25.63.10 x.acme.com # x client host
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
192.168.31.130 oceanspace.top
然后配置完成之后,启动 Nginx ,在浏览器中访问oceanspace.top
就可以访问到指定页面了~~
3.4 日志相关
我们可以通过查阅 Nginx 打印的日志来看到每一笔请求的具体信息,包含用户的 IP 地址信息、跳转来源、终端、以及 URL 的访问量等。
在nginx.conf
配置文件中,默认的一种日志输出格式配置如下:
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
# 配置日志文件地址,声明日志格式
#access_log logs/access.log main;
从输出的日志文件中,我们简单的截取一条日志可以看到:
192.168.31.112 - - [05/Apr/2022:15:49:05 +0800] "GET / HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36"
日志格式字段 | 作用 |
---|---|
remote_addr |
客户端的ip地址 |
remote_user |
客户端的用户名称 |
time_local |
访问时间和时区 |
request |
请求方法 |
status |
响应状态码 如:200 |
body_bytes_sent |
主体内容字节数 如:239 |
http_referer |
记录是从哪个链接访问过来的 |
http_user_agent |
用户使用的代理(浏览器) |
http_x_forwarded_for |
通过代理服务器来记录客户端的ip地址 |
tips: 我们可以使用
shell
脚本完成日志分割,每天生成一份新的日志文件。脚本具体步骤:
- 重命名日志文件
- 让nginx重新从配置中读取日志文件名
- 在新的日志文件中记录日志
3.5 反向代理配置
注意:此案例的前提是需要提前在 Linux 中安装 jdk 和 tomcat
我们原来的需求是访问域名oceanspace.top
可以看到我们自定义在 Nginx 中的页面,现在,我们希望模拟 Nginx 反向代理,让一台 Nginx 服务器对应多态后端服务器(tomcat)。我们希望访问域名可以看到不同的 tomcat 服务器上的不同页面,以此来证明访问了不同的服务器。
首先,我们需要拷贝一个 tomcat ,并修改/conf/server.xml
配置文件中的三处端口号
其次,分别在两个 tomcat 的 webapps 目录下创建一个目录,目录中存放index.html
页面
然后分别启动两个 tomcat
然后,我们需要在nginx.conf
配置文件中配置proxy_pass
代理:
http {
# 对应虚拟主机的配置
server{
listen 80;
server_name oceanspace.top;
location ~/tomcat1/ {
proxy_pass http://127.0.0.1:8080;
}
location ~/tomcat2/ {
proxy_pass http://127.0.0.1:8081;
}
}
}
注意:更改配置文件
nginx.conf
后,执行重加载命令./nginx -s reload
最终浏览器上验证两个地址,都能找到不同的页面
http://oceanspace.top/tomcat1/
http://oceanspace.top/tomcat2/
3.6 负载均衡
3.6.1 什么是负载均衡?
早期的 Web 开发中,我们的服务器压力不是很大,客户端数量不是很多,我们就可以让每一台客户机都来访问一台服务器,但是随着 Web 的不断发展,客户机逐渐增多,显然我们一台服务器是忙不过来了,所以我们就需要去增加后端服务器
早期使用的是 DNS (域名解析系统)来做负载,也就是给客户端解析不同的 IP 地址,让流量直达服务器,但是由于这种方式会有缺陷,如果我们更新了某一个节点下的内容,不能马上生效,具有一定的延时性。慢慢的这种方式就被淘汰了。
后来负载均衡就问世了,这种方式会将客户端的请求首先经过一个负载均衡器(Load Balancer),然后通过一种调度算法,将请求分发到后端服务器。
优点:
- 通过健康检查,避免单点故障
- 当发现节点故障时,从集群中移除,保证应用的高可用
负载均衡器可以处理四大类型的请求,HTTP
/HTTPS
/TCP
/UDP
等。
负载均衡的调度算法:
- 轮询:相当于将服务器从第1台到最后1台,行成一个环状,每接收一笔请求,则从1台开始循环遍历。
- 最小连接:优先选择连接数最少的服务器,适用于会话时间较长的业务处理。
- ip映射:根据请求的ip地址进行散列,让同一ip下的请求都映射到同一服务器上,可以解决session问题。(粘性会话)
3.6.2 负载均衡的配置实现
首先,我们准备两台 tomcat 服务器来模拟后端不同的服务器,分别进入webapps
下
- 创建一个
lb
目录:mkdir lb
- 在
lb
目录下创建一个访问页面 - 编写不同的页面内容
其次,修改nginx.conf
配置:
# http块的层级下
upstream myserver{
# server列表的地址和端口
server 192.168.31.130:8080;
server 192.168.31.130:8081;
}
server {
listen 80;
server_name 192.168.31.130;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
# 将请求映射到负载均衡器中 参数为配置的upstream名称
proxy_pass http://myserver;
}
}
然后浏览器只需要访问http://192.168.31.130/lb/index.html
即可分别轮询两台不同的服务器,做到负载均衡。
轮询方式其权重值默认为1,我们可以对某一台服务器配置加权访问:
# http块的层级下
upstream myserver{
# server列表的地址和端口
server 192.168.31.130:8080 weight=3;
server 192.168.31.130:8081 weight=1;
}
我们也可以根据 IP 地址来固定server
处理,使用ip_hash
来完成:
# http块的层级下
upstream myserver{
# server列表的地址和端口
server 192.168.31.130:8080 weight=3;
server 192.168.31.130:8081 weight=1;
ip_hash;
}
3.7 动静分离
所谓的动静分离,就是将动态资源和静态资源分开管理,在传统的 Web 开发中,前端工程师开发完页面后将其打包交给后端,后端将其部署在服务器中,现在我们希望让html
,css
,js
以及图片等静态资源与后端代码分开管理,分别部署在不同的服务器上。
首先我们需要通过rz
命令上传资源来提供静态资源和动态资源。
其次需要在nginx.conf
中进行配置:
# http块的层级下
upstream myserver{
# server列表的地址和端口
server 192.168.31.130:8080;
}
server {
listen 80;
server_name 192.168.31.130;
#charset koi8-r;
#access_log logs/host.access.log main;
# 动态资源配置
location ~ .*.jsp$ {
proxy_pass http://myserver;
}
# 静态资源配置
location ~ .*\.(gif|jpg|png|html|css|js)$ {
root /usr/local/nginx/image;
# 在浏览器端使用缓存 设置过期时间
expires 3d;
}
}
现在,我们在浏览器中访问静态资源时,Nginx就会匹配我们的请求,将其转发到静态资源服务器,进行返回,访问动态资源就从动态资源服务器进行返回。
3.8 location
匹配规则:
location = /uri
精确匹配location ^~ /uri
前缀匹配,顺序在正则之前location /uri
前缀匹配,顺序在正则匹配之后location ~ pattern
区分大小写的正则匹配location ~* pattern
不区分大小写的正则匹配location /
通用匹配,接收未匹配到其他location的请求匹配顺序: 首先会进行精确匹配,然后会进行前缀匹配,具体顺序按照指令长度,从长到短的顺序依次匹配,但是在正则匹配时,是按照配置文件的顺序依次匹配的,如果不希望前缀匹配后进行正则匹配,那么使用
^~
3.9 URL重写
对 URL 的规范化处理,域名更换时的新旧跳转,一些额外的参数调整等等
server{
listen 80;
server_name duyi123.com;
rewrite ^/(.*) http://www.duyi123.com/$1 permanent;
}
# 访问 duyi123.com 地址栏会变成www.duyi123.com