Nginx基础入门
一、基本认识
Nginx* (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。
其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、简单的配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。
Ngnix的核心名词
正向代理
浏览器 -> 代理服务器 -> 真实服务器
在客户端(如浏览器)配置代理服务器,通过代理服务器进行网络访问的过程,就称为正向代理。
反向代理
客户端对代理是无感知的,因为客户端不需要配置代理,也不知道目标服务器,只知道代理服务器。我们只需要将请求发送到反向代理服务器上,由反向代理服务器去选择目标服务器获取数据后再返回给客户端。此时 反向代理服务器和目标服务器 对外就是一个服务器,暴露的是代理服务器地址,隐藏了真实服务器的IP地址。
负载均衡
最初单一模式
浏览器请求服务器,服务器查询数据库
数据库返回查询结果给服务器,服务器响应结果给浏览器
当出现高并发时服务器可能崩溃
负载均衡技术
浏览器向代理服务器请求,代理服务器又将请求分发到多个服务器,从而降低服务器的压力
动静分离
以前: 把静态资源和动态资源都部署到tomcat里面,每次请求不管是静态资源,还是动态资源,都去请求tomcat。用单服务部署所有的内容。
局限性:请求静态资源和动态资源都去请求tomcat,会带来更大的压力。
现在:
为了加快网站的解析速度,可以把动态页面和静态页面由不同的服务器来解析,加快解析速度,降低原来单个服务器的压力。
阿里云服务器Docker安装Nginx
1、配置阿里云服务器8080和80端口的安全组
2、拉取官方的最新镜像
docker pull nginx:latest
3、查看刚刚下载的镜像
docker pull nginx:latest
4、运行日容器,配置端口映射,开机自启动
docker run --name nginx-test -p 8080:80 -d nginx
5、ip:端口访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bKjlStjF-1630480588666)(C:\Users\wyh\Desktop\截图\Nginx.PNG)]
Nginx 配置文件
首先进入容器内部
docker exec -it 4966e12ea322 /bin/bash
你容器的ID 4966e12ea322
cd /etc/nginx
vim nginx.conf
二、Nginx配置文件
1、全局块
worker_processes 1;
从配置文件到events块之间的内容,主要设置一些影响nginx服务器整体运行的配置指令,主要包括配置运行nginx服务器的用户(组)、允许生成的worker_process数,进程pid存放路径和类型以及配置文件的引入等。
这是nginx服务器并发处理服务的关键,worker_processes值越大,可以支持的并发处理量也越多,但是会受到硬件、软件等设备的制约。
2、events块
events {
worker_connections 1024;
}
events块设计的指令主要影响nginx服务器与用户的网络连接,常用的设置包括是否开启对多worker_process下的网络连接进行序列化,是否允许接收多个网络连接,选取那种事件驱动模型来处理连接请求,每个word_process可以同时支持的最大连接数等。
反向代理、动静分离、高可用都在http块进行配置。
3、http块
代理、缓存、日志定义等绝大多数功能和第三方模块的配置都在这里。需要注意的是,http块也包括http全局块、server块。
3.1、http全局块
http {
include mime.types;
default_type application/octet-stream;
#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;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
}
http全局块配置的指令包括文件引入、MIME_TYPE定义、日志自定义、连接超时时间、单连接请求数上限等。
3.2、server全局
server {
listen 80; #nginx目前监听的端口是80端口
server_name localhost;#主机名称:本地
#charset koi8-r;
#access_log logs/host.access.log main;
location / { #当路径中发现一个"/",就做一些请求跳转
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ { #正则表达式 当访问路径满足这个规则,就按如下配置操作
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
这块和虚拟主机有密切联系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了节省互联网服务器硬件成本。
每个http块可以包括多个server块,而每个server块就相当于一个虚拟主机。
而每个server块也分为全局server块,以及可以同时包含多个location块
全局server块 | 最常见的配置是本虚拟机主机的监听配置和本虚拟机的名称或IP配置 |
---|---|
location块 | 一个server块可以配置多个location块 这块的主要功能是基于nginx服务器接收到的请求字符串(例如server_name/uri_string),对虚拟主机名称(也可以是IP别名)之外的字符串(例如前面的/uri_string)进行匹配,对特定的请求进行处理,地址定向、数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。 |
三、反向代理
反向代理1
浏览器 -> 域名 -> nginx地址(请求转发) -> 具体的ip:端口号
- 1.安装tomcat并启动,端口号默认8080。
- 2.修改hosts文件。因为没有域名,就在本地做配置,让它转发到nginx中,nginx再去请求tomcat
* Hosts文件主要作用是定义IP地址和主机名的映射关系,是一个映射IP地址和主机名的规定。可以用文本文件打开!当用户在浏览器中输入网址时,系统会首先自动从Hosts文件中寻找对应的IP地址,一旦找到,浏览器会立即打开对应网页,如果没有找到,则浏览器会将网址提交DNS服务器进行IP地址解析。
# hosts文件加入IP地址和域名
IP地址 www.123.com
#Nginx配置文件
server {
listen 80;
server_name IP地址; #1.将localhost改成IP地址
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
proxy_pass http://127.0.0.1:8080; #2.配置转发地址
index index.html index.htm;
}
通过域名直接访问的80端口。通过nginx能给它转发到内部的8080端口上去。而浏览器不能直接访问8080(需要对外暴露端口才能访问),要通过80转发过去,这个过程成为请求转发。
浏览器输入www.123.com,显示的就是tomcat主页面
反向代理2
目标:使用nginx反向代理,根据访问的路径跳转到不同端口的服务中。
nginx监听端口为9001
访问http://IP地址:9001/edu/a.html,直接跳转到127.0.0.1:8081
访问http://IP地址:9001/vod/a.html,直接跳转到127.0.0.1:8080
linux服务器创建两个tomcat服务器,其实是两个解压文件,分别配置自己的访问端口
- 在原来的tomcat/webapps/下,新建目录/edu,并创建a.html
<!DOCTYPE html>
<html>
<body>
<h1>/edu/8080</h1>
</body>
</html>
2.重新解压一个tomcat,并在webapps创建/vod,创建a.html
<!DOCTYPE html>
<html>
<body>
<h1>/vod/8081</h1>
</body>
</html>
修改配置文件,将端口号改为8081,其他的端口十位改为1,然后启动tomcat
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8015" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8019" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
修改nginx配置文件
在http块中添加如下配置
server {
listen 9001;
server_name IP地址;
location ~ /edu/ {
proxy_pass http://127.0.0.1:8080;
}
location ~ /vod/ {
proxy_pass http://127.0.0.1:8081;
}
验证
浏览器访问 http://IP地址:9001/vod/a.html, http://IP地址:9001/edu/a.html
nginx配置文件中的location是配置请求转发的url
location [ = | ~ | ~* | ^~ ] url{
# =:用于不含正则表达式的uri前,要求请求字符串与uri严格匹配,如果匹配成功,就停止继续向下搜索,并立即处理请求。
# ~:用于表示uri包含正则表达式,并且区分大小写。
# ~*:用于表示uri包含正则表达式,并且不区分大小写
# ^~:用于不含正则表达式的uri前,要求nginx服务器找到表示uri和请求字符串匹配度最高的location后,立即使用此location处理请求,而不再使用location块中的正则uri和请求字符串做匹配。
}
四、负载均衡
负载均衡: 将原来的请求集中到单个服务器的情况改为将请求分发到多个服务器上,将负载分发到不同的服务器 。
简单来说,一个请求交给多个服务器处理,这一次交给这个ip:端口号响应;刷新当前页面,交给另一个ip:端口响应。
1.准备工作
1.准备2台tomcat服务器,一台8080,一台8081
2.在2台tomcat的webapps目录下,创建a.html文件用于测试
8080/a.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1>8080</h1>
</body>
</html>
8081/a.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1>8081</h1>
</body>
</html>
2.配置nginx
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#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;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
# 负载均衡1
upstream myserver {
server IP地址:8080;
server IP地址:8081;
}
server {
listen 80;
server_name IP地址;
#charset koi8-r;
#access_log logs/host.access.log main;
# 负载均衡2
location / {
root html;
proxy_pass http://myserver;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# 反向代理
server {
listen 9001;
server_name IP地址;
location ~ /edu/ {
proxy_pass http://127.0.0.1:8080;
}
location ~ /vod/ {
proxy_pass http://127.0.0.1:8081;
}
}
3.验证
频繁访问 http://IP地址/edu/a.html,返回的结果既有8080,也有8081
负载均衡规则:
1、轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
2、 weight
weight代表权重,默认为1,权重越高,被分配的客户端越多。
指定轮询几率,weight和访问几率成正比,用于后端服务器性能不均的情况。
upstream server_pool{
server 172.168.0.1:8080 weight=10;
server 172.168.0.1:8081 weight=5;
}
3、ip_hash
每个请求按访问IP的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。例如
upstream server_pool{
ip_hash;
server 172.168.0.1:8080;
server 172.168.0.1:8081;
}
4、fair方式
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
upstream server_pool{
server 192.168.5.21:8080;
server 192.168.5.21:8081;
fair;
}
访问网址,负载均衡分发到8080和8081。先访问8080,没有访问到,再去访问8081,看谁的响应时间短,就先给谁。
五、动静分离
nginx动静分离简单来说就是把动态跟静态请求分开,不能理解成知识单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态跟静态请求分开,可以理解成使用nginx处理静态页面,tomcat处理动态页面。
动静分离的目的:
- 提高访问的效率,让我们的请求更高效。动态就专门访问tomcat,静态就专门反问静态资源服务器。
- 设置浏览器缓存提高访问效率:通过location指定不同的后缀名实现不同的请求转发,通过expires参数设置,可以使浏览器在缓存过期时间内,减少服务器之间的请求和流量。具体Expires定义:是给一个资源设定一个过期时间,也就是说无需去服务端验证,直接通过浏览器自身确认是否过期即可,所以不会产生额外的流量。此种方法非常适合不经常变动的资源。(如果经常更新的文件,不建议使用Expire来缓存)。如果设置3d,就表示这3天之内访问URL,发送一个请求,比对服务器该文件最后更新时间是否变化。未变化,则不会从服务器抓取,返回状态码304;如果有修改,则直接从服务器重新下载,返回状态200.
通过nginx访问到文件,而不通过tomcat
在/data/创建www和image2个目录。www用于存放网页,image用于存放图片。
static_a.html
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
</head>
<body>
<h1>这是一个静态页面,啥都没有</h1>
</body>
</html>
# 长城汽车的看到,请给个5毛费用
wget -O h6_2.jpg https://xxx.jpg
配置过程
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#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;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
# 负载均衡1
upstream myserver {
server IP地址:8080;
server IP地址:8081;
}
server {
listen 80;
server_name IP地址;
#charset koi8-r;
#access_log logs/host.access.log main;
# 动静分离
location /www/ {
root /data/;
}
location /image/ {
root /data/;
autoindex on;
}
# 负载均衡2
location / {
root html;
proxy_pass http://myserver;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# 反向代理
server {
listen 9001;
server_name IP地址;
location ~ /edu/ {
proxy_pass http://127.0.0.1:8080;
}
location ~ /vod/ {
proxy_pass http://127.0.0.1:8081;
}
}
重启nginx,验证结果
./sbin/nginx -s reload
访问 http://IP地址/www/static_a.html
六、Nginx集群
普通模式的问题
发送一个请求,先到nginx,再由nginx转发到不同的服务器中去。
问题:
- 1.tomcat宕机,会自动从列表中剔除。
- 2.nginx宕机,请求就无法实现
高可用
高可用就是nginx宕机了,依然可以正常请求。
2台Nginx服务器,1台主服务器,1台从服务器。主nginx挂掉,就自动切换到从nginx上,让它作为主nginx进行网络访问。
主从服务器需要用keepalived,其类似一个路由,通过一组脚本来检测当前的nginx服务器是否还活着。如果还活着,就进行访问;如果宕机了,就切换到另一台备用的nginx。
**虚拟IP:**这个IP不存在,但我们是通过这个IP访问。假如虚拟IP是192.168.17.50,现在对外是用192.168.17.50进行访问,而把这个IP绑定到服务器中,类似绑定一个网卡。当keepalived检测到主nginx挂掉之后,把虚拟Ip绑定到备份服务器中。
按照这个过程,就可以实现nginx的高可用效果,这是主-从模式。
安装配置keepalived
# 安装keepalived
yum install -y keepalived
# 确认安装成功
rpm -q -a keepalived
keepalived配置文件:/etc/keepalived/
! Configuration File for keepalived
#全局配置
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL #通过这个名字能访问到主机,其余用处不大
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
# 相关脚本配置
vrrp_script chk_http_port{
script "/usr/local/src/nginx_check.sh"
interval 2 #检测脚本执行的间隔
weight 2 #权重。当脚本的条件成立,把当前的权重加2;如果值为负数(-20),就减少20。通过修改weight来改变主从服务器
}
# 虚拟IP的配置
vrrp_instance VI_1 {
state MASTER #主MATER 从BACKUP
interface enp0s3 #网卡 通过ifconfig查看
virtual_router_id 51 #主从机的virtual_router_id必须相同
priority 100 #主从机取不同的优先级,主机值较大,备份机值较小
advert_int 1 #心跳时间间隔,用于检测主机或服务器是否还活着,默认1秒。表示每隔多长时间发生一个心跳
authentication { #权限校验方式
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { #通过它就可以完成keepalived的配置
172.16.1.50
}
}
从服务器只需要修改虚拟IP的state和priority即可。
需要的脚本/usr/local/src/nginx_check.sh
#!/bin/bash
A=`ps -C nginx -no-header | wc -l`
if [ $A -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 2
if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
killall keepalived
fi
fi
启动nginx和keepalived
在两台服务器中分别启动nginx和keepalived
./nginx -s stop
./nginx
systemctl start keepalived.service
查看虚拟IP
启动成功后,进入服务器,可以查看到虚拟IP已经绑定到网卡
ip a
浏览器验证
1.浏览器输入地址 http://172.16.1.50/ ,能访问到nginx,证明主服务器可用。
2.主服务器停止nginx和keepalived,再次访问 http://172.16.1.50/ ,依然能访问到nginx,证明从服务器可用
# 先停止keepalived
systemctl stop keepalived.service
# 再停止nginx
./nginx -s stop
3.从服务器停止nginx和keepalived,再次访问 http://172.16.1.50/ ,应该访问失败。
七、Nginx原理
master和worker
在nginx搭建之后,在linux系统中,其实是有2个进程,一个进程叫master,一个进程叫worker。
# 查看nginx进程
ps -ef|grep nginx
master是管理员,把任务分给worker,有worker执行具体的任务。
worker是怎么执行工作的
当client发送一个请求到nginx,首先由master把请求分配到worker去执行。
问题:一个管理员下面可能会有很多的worker,那么worker是怎么得到这个任务的呢?
这里用到一个机制,不是平均分配,也不是轮询,而是争抢。即所有的worker采用争抢的机制抢到这个任务,然后调用tomcat,活用反向代理,指向我们的操作。
master-worker机制的好处
首先,对于每个worker的进程来说,独立的进程,不需要加锁,所以省略了锁带来的开销。同时在编程以及问题查找时,也会方便很多。
其次,采用独立的进程,可以让互相之间不受影响。一个进程退出后,其他进程继续进行争抢任务和工作,工作不会中断,master进程则很快启动新的worker进程。当然worker进程的异常退出,肯定是程序有bug了。异常退出,会导致当前worker让所有请求失败,不过不会影响到所有请求,所以降低了风险。
热部署
在生产环境,nginx是不能停止的,而使用热部署就能解决不停止nginx完成部署的问题。
比如现在有4个worker,加入当前任务被worker1争抢到了。当使用 ./nginx -s reload 进行热部署时,worker1不做变化,继续处理任务。未执行任务的worker就把nginx重新进行加载。如果说有1个新的请求,worker1就不参与争抢,其他3个任务进行争抢,这是3个任务已经是重新加载之后的内容。
worker1则等待原来的任务执行完毕后,重新加载,获得最新的配置。
设置多少个worker,才是合适的
nginx同redis蕾丝,都采用了io多路复用机制,每个worker都是一个独立的进程。但每个进程里只有一个祝线程。通过异步非阻塞的方式来处理请求,即便是成千上万个请求也不在话下。每个worker的县城可以把一个CPU的性能发挥到极致。所以worker数和服务器的CPU数相等是最为适宜的。设少了,浪费CPU;设多了会造成CPU频繁切换上下文带来的损耗。
windows没有io多路复用机制,在windows中功能虽然有,但它并不能把它的效能发挥到最大限度。所以,nginx、redis一般安装到Linux系统中,把它的性能发挥到最大限度。
连接数 worker-connection
问题:发送一个请求,占用几个连接数?
答案:2个或者4个
只访问静态资源,2个连接数;当使用tomcat时,需要4个连接数
问题2: nginx有一个master,有4个worker,每个worker支持的最大连接数是1024,每个worker支持的最大并发数是多少?
worker最大支持的连接数:
这个值是表示每个worker的进程所能建立连接的最大值。所以,一个nginx能建立的最大连接数,应该是 worker_connections * worker_processes,当然这里所说的是最大连接数。
对于http请求本地资源来说,,如果是支持http1.1的浏览器每次访问要占用2个连接,所以普通的静态访问最大并发量是( worker_connections * worker_processes)/2;
而如果是http作为反应代理,最大并发数量是(worker_connections * worker_processes)/4。因为反向代理服务器,每个并发会建立与客户端的连接和与后端服务器的连接。
两个数字相比取大的,因此最大并发数为( worker_connections * worker_processes)/2。
总结
1.nginx采用master-worker的方式
2.worker采用争抢方式进行工作的
3.可以根据CPU数量设置worker数量
4.发送请求的时候,每个请求占有2个或4个连接数
5.worker支持的最大并发数