第一章、Nginx的目录结构以及运行原理
Nginx的目录结构
[root@localhost ~]# tree /usr/local/nginx
/usr/local/nginx
├── client_body_temp # POST 大文件暂存目录
├── conf # Nginx所有配置文件的目录
│ ├── fastcgi.conf # fastcgi相关参数的配置文件
│ ├── fastcgi.conf.default # fastcgi.conf的原始备份文件
│ ├── fastcgi_params # fastcgi的参数文件
│ ├── fastcgi_params.default
│ ├── koi-utf
│ ├── koi-win
│ ├── mime.types # 媒体类型
│ ├── mime.types.default
│ ├── nginx.conf #这是Nginx默认的主配置文件,日常使用和修改的文件
│ ├── nginx.conf.default
│ ├── scgi_params # scgi相关参数文件
│ ├── scgi_params.default
│ ├── uwsgi_params # uwsgi相关参数文件
│ ├── uwsgi_params.default
│ └── win-utf
├── fastcgi_temp # fastcgi临时数据目录
├── html # Nginx默认站点目录
│ ├── 50x.html # 错误页面优雅替代显示文件,例如出现502错误时会调用此页面
│ └── index.html # 默认的首页文件
├── logs # Nginx日志目录
│ ├── access.log # 访问日志文件
│ ├── error.log # 错误日志文件
│ └── nginx.pid # pid文件,Nginx进程启动后,会把所有进程的ID号写到此文件
├── proxy_temp # 临时目录
├── sbin # Nginx 可执行文件目录
│ └── nginx # Nginx 二进制可执行程序
├── scgi_temp # 临时目录
└── uwsgi_temp # 临时目录
其中较为核心的目录是存放配置文件的目录conf,静态资源网页目录html以及启动nginx的目录sbin
首先查看html目录:
然后查看config目录:
最后就是sbin目录,这个目录只有一个可执行文件,用于开启nginx
Nginx的运行原理
nginx启动原理
在Nginx启动之后,首先会开启一个master进程和多个worker进程。master进程用于读取并校验配置文件,配置文件中会设置开启几个worker进程,master会管理这些worker进程。worker进程用来接收用户的请求,worker进程解析用户请求读取相应文件之后返回用户。
master进程对worker进程的管理:
接收来自外界的信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程退出后(异常情况下),会自动重新启动新的worker进程。worker进程主要处理基本的网络事件,多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。worker进程的个数是可以设置的,一般会设置与机器cpu核数一致,这里面的原因与nginx的进程模型以及事件处理模型是分不开的。
Nginx的配置文件
初始的配置文件中有很多注释,很影响观看,去掉原有注释后的配置文件如下:
worker_processes 1; #worker工作进程的数量,建议设置为cpu核心数或者auto自动检测,注意Windows服务器上虽然可以启动多个processes,但是实际只会用其中一个
events {
#单个进程最大连接数(最大连接数=连接数*进程数)
#根据硬件调整,和前面工作进程配合起来用,尽量大,但是别把cpu跑到100%就行。
worker_connections 1024;
}
http {
include mime.types; #见下面第一点
#默认文件类型,如果mime.types预先定义的类型没匹配上,默认使用二进制流的方式传输
default_type application/octet-stream;
sendfile on;见下面第二点
#长连接超时时间,单位是秒
keepalive_timeout 65;
#虚拟主机的配置,可以配置多个
server {
#监听端口
listen 80;
#域名,可以有多个,用空格隔开,域名和端口号组成一个虚拟主机的完整标识
server_name localhost;
#配置根目录以及默认页面,默认显示的是html页面下的index.html
location / {
root html;
index index.html index.htm;
}
#出错页面配置
error_page 500 502 503 504 /50x.html;
#/50x.html文件所在位置
location = /50x.html {
root html;
}
}
}
include mime.types;
#引入的配置文件,文件扩展名与文件类型映射表,由于浏览器本身无法识别文件类型,所以服务器会将文件对应的类型和解析方式一同返回给浏览器。这个配置文件写了对不同文件的操作方式:下载或者直接展示播放。
sendfile on;
nginx对于文件的调用,首先将文件加载到nginx服务器的内存中,然后在将内存通过网络接口发送到互联网。
sendfile设置为on之后,nginx会发送一个sendfile信号给网络接口,然后网络接口会直接到磁盘中读取数据,这时候少了一步文件拷贝。所以这个也就是网络搞笑传输,也就是数据0拷贝。
第二章、Nginx虚拟主机与域名解析
虚拟主机与域名解析
虚拟主机是指使用特殊的软硬件技术,把一台运行在因特网上的服务器主机分成一台台“虚拟”的主机,每一台虚拟主机都具有独立的域名,具有完整的Internet服务器(WWW、FTP、Email等)功能,虚拟主机之间完全独立,并可由用户自行管理,在外界看来,每一台虚拟主机和一台独立的主机完全一样。
域名解析就是域名到IP地址的转换过程,IP地址是网路上标识站点的数字地址,为了简单好记,采用域名来代替ip地址标识站点地址,域名的解析工作由DNS服务器完成。
域名、dns、ip地址的关系
域名是相对网站来说的,IP是相对网络来说的。当输入一个域名的时候,网页是如何做出反应的?
输入域名---->域名解析服务器(dns)解析成ip地址—>访问IP地址—>完成访问的内容—>返回信息。
Internet上的计算机IP是唯一的,一个IP地址对应一个计算机。
一台计算机上面可以有很多个服务,也就是一个ip地址对应了很多个域名,即一个计算机上有很多网站。
虚拟主机原理
虚拟主机是为了在同一台物理机器上运行多个不同的网站,提高资源利用率引入的技术。
一般的web服务器一个ip地址的80端口只能正确对应一个网站。现在需要使用同一个ip地址和同一个端口号来访问不同的网站资源。一般情况下这样是无法区分用户请求来完成区分需要转发的网站资源的。
虚拟主机则是通过配置域名信息来完成这一个过程的。由于一个ip地址可以对应多个域名解析,所以访问的时候可以访问多个域名来转换成同一个ip地址到相同的服务器。服务器会拿到这个域名和对应的端口号,这样就可以根据这两者来确定访问那一个虚拟主机。
这时候对于用户来说,访问了不同的域名;对于一台计算机来说,访问了同一个ip地址的同一个端口号;最终服务器通过不同域名来转发不同的网站资源。实现这个的本质方式就是一个ip地址可以对应多个域名解析。
Nginx实现虚拟主机的转发
修改配置文件,配置两台虚拟主机
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 88;
server_name www.mmban.com;
location / {
root html;
index aa.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
server {
listen 88;
server_name www.mmban.*;
location / {
root html;
index aa.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
配置host映射
这时候开启nginx服务之后,访问www.mmban.com:88就会被本机的host转换为ip去访问到nginx服务器,服务器拿到这个域名加端口的访问之后,会转发到设置好的aa.html文件上还给浏览器解析显示。访问www.mmban.net:88之后会转发到index.html上,这样就实现了虚拟主机的转发。
一个主机监听多个端口的方式(空格隔开):server_name www.mmban.com www.mmban.net;
更改配置文件之后需要执行./nginx -s reload
ServerName匹配规则
完整匹配:可以配置多个域名
server_name www.mmban.com www.mmban.net;
通配符匹配:前后都可以
server_name www.mmban.*;
正则匹配
server_name ~^[0-9]+\.mmban.cn$;
正则匹配格式,必须以~开头,比如:server_name ~^www\d+\.example\.net$;。如果开头没有~,则nginx认为是精确匹配。在逻辑上,需要添加^和$锚定符号。注意,正则匹配格式中.为正则元字符,如果需要匹配.,则需要反斜线转义。如果正则匹配中含有{和}则需要双引号引用起来。
需要注意的是精确匹配的优先级大于通配符匹配和正则匹配。
第三章、反向代理在系统结构中的应用场景
反向代理
反向代理就是创建一个服务器用来在服务器内网代理互联网转发过来的请求。
正向代理是代理用户的请求到互联网,也就是网关。
反向代理服务器通常有两种模型,一种是作为内容服务器的替身,另一种作为内容服务器集群的负载均衡器。
作内容服务器的替身
如果你的内容服务器具有需要保护的数据,可以在防火墙外部设置一个代理服务器用于转发请求。用户访问的时候会到达这个代理服务器,代理服务器会截取该消息更改标头中的url,然后通过特定的防火墙路线将请求发送到内容服务器,内容服务器还是在防火墙的保护下。而且客户并不知道真实服务器的地址,这样会更加安全。
作为内容服务器的负载均衡器
可以在一个组织内使用多个代理服务器来平衡各 Web 服务器间的网络负载。在此模型中,可以利用代理服务器的高速缓存特性,创建一个用于负载平衡的服务器池。此时,代理服务器可以位于防火墙的任意一侧。如果 Web 服务器每天都会接收大量的请求,则可以使用代理服务器分担 Web 服务器的负载并提高网络访问效率。
对于客户机发往真正服务器的请求,代理服务器起着中间调停者的作用。代理服务器会将所请求的文档存入高速缓存。如果有不止一个代理服务器,DNS 可以采用“轮询法”选择其 IP 地址,随机地为请求选择路由。客户机每次都使用同一个 URL,但请求所采取的路由每次都可能经过不同的代理服务器。
可以使用多个代理服务器来处理对一个高用量内容服务器的请求,这样做的好处是内容服务器可以处理更高的负载,并且比其独自工作时更有效率。在初始启动期间,代理服务器首次从内容服务器检索文档,此后,对内容服务器的请求数会大大下降。
Nginx配置反向代理
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream httpds{
server 192.168.200.131:88 weight=8;
server 192.168.200.132:88 weight=2;
}
server {
listen 88;
server_name www.mmban.com;
location / {
proxy_pass http://httpds;
# root html;
# index aa.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
通过proxy_pass属性可以设置代理的内容,比如可以设置为:proxy_pass http://www.baidu.com;
基于反向代理的负载均衡
上述的配置文件就是一个基于反向代理的负载均衡,将代理结果单独使用upstream定义出来,里面写服务器地址;这样可以直接实现负载均衡,负载均衡策略一般是轮询,可以设置权重,down,backup等参数。
权重就是访问这台服务器的概率,down就是表示该服务器下机了无法访问,backup是备用服务器,当没有服务器可用的时候就访问这台。
其他负载均衡策略
其他负载均衡策略(不常用)
ip_hash
根据客户端的ip地址转发同一台服务器,可以保持会话,但是很少用这种方式去保持会话,例如我们当前正在使用wifi访问,当切换成手机信号访问时,会话就不保持了。
least_conn
最少连接访问,优先访问连接最少的那一台服务器,这种方式也很少使用,因为连接少,可能是由于该服务器配置较低,刚开始赋予的权重较低。
url_hash(需要第三方插件)
根据用户访问的url定向转发请求,不同的url转发到不同的服务器进行处理(定向流量转发)。
fair(需要第三方插件)
根据后端服务器响应时间转发请求,这种方式也很少使用,因为容易造成流量倾斜,给某一台服务器压垮。
动静分离
为了提高网站的响应速度,减轻程序服务器(Tomcat,Jboss等)的负载,对于静态资源,如图片、js、css等文件,可以在反向代理服务器中进行缓存,这样浏览器在请求一个静态资源时,代理服务器就可以直接处理,而不用将请求转发给后端服务器。对于用户请求的动态文件,如servlet、jsp,则转发给Tomcat,Jboss服务器处理,这就是动静分离。即动态文件与静态文件的分离。
第四章、Nginx在集群和http安全性的访问
nginx高可用及Keepalived实战
nginx集群在搭建的时候对高可用有较高的要求,一般需要nginx来对服务反向代理,做一个转发的功能。但是如果这个时候这台用来转发的核心nginx挂掉了就会导致服务直接不可用,所以需要使用两台nginx做一个备用,一台挂掉了还可以走另一台。
但是这样一来又需要一台nginx到前面转发,一直这样下去没有止境,所以需要去中心化。也就是让两台机器互相监管,使用同一个虚拟ip。
keepalived就是这样一个用于实现该功能的软件,他可以同时下载在两台同样功能的nginx中。由他将两台nginx服务器放在同一个组里面,给这个组一个或者多个ip。这一个组里面的两台服务器会互相检测是否挂掉,都没有挂掉的时候,由其中一台竞争力高(在keepalived中设置)的持有这个虚拟ip,外面的服务直接访问这个ip就可以了。如果这台用来转发的nginx服务器挂掉了,另一台备用的服务器会接替这个虚拟ip,这样一来就保证了高可用。
keeplived概述:
Keepalived软件起初是专为LVS负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现高可用的VRRP功能。因此,Keepalived除了能够管理LVS软件外,还可以作为其他服务(例如:Nginx、Haproxy、MySQL等)的高可用解决方案软件。VRRP出现的目的就是为了解决静态路由单点故障问题的,它能够保证当个别节点宕机时,整个网络可以不间断地运行。所以,Keepalived 一方面具有配置管理LVS的功能,同时还具有对LVS下面节点进行健康检查的功能,另一方面也可实现系统网络服务的高可用功能。
keepalived服务的三个重要功能:
管理LVS负载均衡软件
实现LVS集群节点的健康检查中
作为系统网络服务的高可用性(failover)
安装keepalived:yum install -y keepalived
keepalived配置文件:许多配置项不用过多关注,可以使用这样的配置;
! Configuration File for keepalived
global_defs {
router_id lb111 #服务器在组里面的名字
}
vrrp_instance liu { #组的名字
state MASTER #组里面持有ip的主机
interface ens33 #你的网卡配置文件名称
virtual_router_id 51
priority 100 #挂掉之后的竞争力
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.200.100 #虚拟ip
}
}
启动服务
systemctl start keepalived
查看服务状态
systemctl status keepalived
查看ip
ip addr
可以看到,这里有本机自己的ip,还有一个是keepalived虚拟出来的ip,两个ip都可以访问到这台服务器。
开启第二台虚拟机,修改配置文件,注意两个配置文件只需要修改一部分东西
! Configuration File for keepalived
global_defs {
router_id lb110 #修改这个名称
}
vrrp_instance liu {
state BACKUP #这个是标识备用的服务器
interface ens33
virtual_router_id 51
priority 50 #修改这个竞争力
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.200.100
}
}
启动之后查看ip
就发现这台服务器没有持有keepalived虚拟的ip,这个时候使用主机(客户端)ping这两台虚拟机(服务器),然后ping到一半关闭持有虚拟ip的那台服务器(模拟挂掉)。
这时候在备用机上面查看ip
发现keepalived的虚拟ip到这台机器上了。对于客户端来说没有什么区别。
Nginx配置防盗链
什么是盗链
盗链就是某一个服务商,自己开一个网站但是不做具体的内容,而是通过技术手段直接跳转到别人的网站偷取别人的资源(比如一些资源网站)。这样就可以骗取用户的浏览量和点击量,这个服务商一般不提供资源或者很少的资源,真正的服务商的不到任何收益。
REFERER防盗链
referer是HTTP协议中request header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理。如果referer信息不是来自本站,就阻止访问或者跳到其它链接。
Referer防盗链容易破解。
Token防盗链(时间戳防盗链)
Token防盗链通过对时间有关的字符串进行签名,将时间和签名信息通过一定的方式传递给CDN节点服务器(CDN,Content Delivery Network,即内容分发网络。)作为判断依据,CDN 节点则会根据 URL 的加密形式,取出对应的过期时间,和当前服务器时间进行比较,确认请求是否过期,过期的话,则直接拒绝;如果时间未过期,CDN 节点将根据约定的签名算法和密文,计算加密后的值,与 URL 中的携带的加密串进行比较,如果相同,则请求会被认为是合法的,不合法的请求可以采取禁止访问或其他操作。
nginx防盗链配置
可以在nginx的配置文件中设置一下,如果不是本站,或者需要的ip访问,就返回错误页面,反之就放行。比如下面对图片资源的访问,如果不是由102访问就返回错误,防止其他的网站ip偷取本网站内容。
location ^~/images/ {
valid_referers 192.168.8.102; #valid_referers 指令,配置是否允许 referer 头部以及允许哪些 referer 访问。192.168.8.102不是ip而是域名(去掉http:// 前缀)
if ($invalid_referer) { # 注意这里if后要加空格
return 403; ## 返回错误码
}
root /www/resources;
}
valid_referers解释
可以同时携带多个参数,表示多个 referer 头部都生效。
参数值
none:允许没有 referer 信息的请求访问,即直接通过url访问。
blocked:请求头Referer字段不为空(即存在Referer),但是值可以为空(值被代理或者防火墙删除了),并且允许refer不以“http://”或“https://”开头,通俗点说就是允许“http://”或"https//"以外的请求。
server_names:若 referer 中站点域名与 server_name 中本机域名某个匹配,则允许该请求访问
其他字符串类型:检测referer与字符串是否匹配,如果匹配则允许访问,可以采用通配符*
正则表达式:若 referer 的值匹配上了正则,就允许访问
invalid_referer 变量
允许访问时变量值为空
不允许访问时变量值为 1
server {
server_name referer.test.com;
listen 80;
error_log logs/myerror.log debug;
root html;
location / {
valid_referers none server_names
*.test.com www.test.org.cn/nginx/;
if ($invalid_referer) {
return 403; # 返回错误码
}
return 200 'valid\n';
}
}
# none:表示没有 referer 的可以访问
# server_names:表示本机 server_name 也就是 referer.test.com 可以访问
# *.test.com:匹配上了正则的可以访问
# www.test.org.cn/nginx/:该页面发起的请求可以访问
使用curl测试防盗链
curl可以模拟一个站点到另一个站点的访问操作,然后返回一些信息,不响应页面。
使用curl测试
从baidu访问过来的请求:
http协议的安全性
一般使用http协议的网络请求是不安全的,你请求的信息会通过你家里的wifi连接到村里的等等一系列节点,每个节点都可以保留你的数据。数据一般只会通过对称加密算法来做一些简单的加密,但是这些加密算法都是开源的,所以很轻易就可以将你的信息截获然后解包。
非对称算法
非对称算法的使用过程
非对称算法是有一个公钥和私钥,服务器保留私钥和公钥。当用户请求服务器的时候,用户首先下载服务器的公钥,明文通过公钥加算法变成密文。然后这个密文在网络中传输,但是除了服务器端没人能解开这个数据。所以存在一定的安全性。在返回数据的时候,使用私钥加算法加密数据,由客户端来解密接收数据。
非对称算法的破解方式
用户在访问的时候,服务器端下发公钥,然后中途这个公钥在某个节点呗拦截,这个节点自己提供一对公钥和私钥,然后将虚假的公钥给用户,用户加密之后将这个密文返回,节点拿到这个密文使用自己的私钥解密之后查看并篡改数据之后使用服务器真实的公钥加密发送给服务器端。这样就破解了非对称算法。
CA认证机构
有很多第三方的认证机构,一般的服务器将自己的公钥域名等信息传递给ca认证机构,ca认证机构将服务器的域名公钥等信息通过私钥加上算法的形式加密成密文,这个密文就是证书。认证机构将这个证书传递给服务器。
当用户请求服务器的时候,服务器会将证书下发给用户,中途传递的时候别人只能用ca认证机构的公钥和算法去解密你的证书信息,无法串改之后在加密,因为ca的私钥只有自己持有。用户拿到证书之后通过操作系统内置的ca公钥来对证书解密,(重要的就是ca公钥存在计算机操作系统中,如果可以吧你要访问的服务器公钥一开始就存放到操作系统,这样也可以保证安全,但是服务器太多,这是不可能的,所以只能存放第三方的部分公钥)解密之后拿到服务器的公钥就可以和服务器交互了。
https协议就是HTTP加上一个ssl安全套接字协议,底层就使用了ca机构认证的非对称算法等。所以https比http安全的多。