Nginx实战
1、nginx简介
常用web服务器
1、Apache服务器
2、Lighttpd服务器
3、Tomcat服务器
4、IBM WebSphere服务器
5、Microsoft IIS
选择nginx的理由
1、支持高并发连接
2、内存消耗小
3、成本低廉
4、其它理由
2、Nginx的安装与配置
安装Nginx所需要的资源
需要一个Linux服务器,选择CentOS。
CentOS介绍:CentOS是基于RedHat Enterprise Linux源代码重新编译、去除RedHat商标的产物,各种操作、使用和RedHat没有区别。CentOS完全免费,修正了RedHat的很多Bug,但是CentOS不向用户提供技术支持,也不负任何商业责任。
安装编译Nginx需要第三方的工具:
# yum install gcc gcc-c++ autoconf automake zlib zlib-devel openssl openssl-devel pcre pcre-devel -y
c、c++语言的编译器:gcc gcc-c++
创建makefile的工具:autoconf automake
gzip模块的依赖库:zlib zlib-devel
ssl功能的依赖库:openssl openssl-devel
rewrite模块的依赖库:pcre pcre-devel
Nginx的下载
官网 https://www.nginx.org/
https://www.nginx.org/download
Nginx安装与使用
Nginx安装:
1. 停止原有web服务器:
2. 添加普通用户账号来运行nginx:
# useradd -M -s /sbin/nologin nginx
3. 解压并安装Nginx:
# wget https://nginx.org/download/nginx-1.22.0.tar.gz
# tar xf nginx-1.22.0.tar.gz
# cd nginx-1.22.0
# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module --sbin-path=/usr/sbin/
若预编译出现报错,一般都是缺少一些软件包
yum install gcc gcc-c++ autoconf automake zlib zlib-devel openssl openssl-devel pcre pcre-devel -y
# make && make install
----------------------------------------------------------------------------------
--prefix=/usr/local/nginx #指定安装路径
--with-http_stub_status_module #启用service status页,默认不启用
--with-http_ssl_module #启用ssl模块,以支持https请求
--sbin-path=/usr/sbin/ #指定二进制命令的路径
4. 启动:
# nginx
--------------------------------------------------------
nginx命令常用选项:
-v 查看版本号
-V 查看版本号及编译选项
-s 给主进程发送信号.可接 stop 停止 | quit 退出 | reopen 重启| reload 重新加载配置
-t 测试配置是否正确
-c 指定配置文件,默认为 conf/nginx.conf
5. 查看启动状态:
# netstat -tanp|grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 5535/nginx
6. 测试主页是否可以访问
3、Nginx的基本配置和优化
Nginx配置示例
nginx主配置文件主要有以下几大块
1、全局块:配置影响nginx全局的指令。一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等。
2、events块:配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。epoll
3、http块:可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等。
4、server块:配置虚拟主机的相关参数,一个http中可以有多个server。
5、location块:配置请求的路由,以及各种页面的处理情况。
[root@clone1 nginx]# vim /usr/local/nginx/conf/nginx.conf
#user nobody; #nginx用户及组,如果用户和组名一样可只写一个
worker_processes 1; #定义了nginx对外提供web服务时的worker进程数。
#最优值取决于许多因素,包括(但不限于)CPU核的数量、存储数据的硬盘 数量及负载模式。
#不能确定的时候,将其设置为可用的CPU核心数将是一个好的开始(设置为“auto”将尝试自动检测它)
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024; #每个进程的最大连接数,根据需要调整大小
}
http {
include mime.types; #文件扩展名与文件类型映射表
default_type application/octet-stream;
server_tokens off; #隐藏软件版本号
#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;
server {
listen 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;
# }
#}
}
虚拟主机
1、基于IP的虚拟主机
/sbin/ifconfig ens33:1 192.168.105.201 broadcast 192.168.105.255 netmask 255.255.255.0 up
/sbin/route add -host 192.168.105.201 dev ens33:1
/sbin/ifconfig ens33:2 192.168.105.202 broadcast 192.168.105.255 netmask 255.255.255.0 up
/sbin/route add -host 192.168.105.202 dev ens33:2
将其写入/etc/rc.local即可开机自启
# 第一个虚拟主机
server {
# 监听的ip和端口
listen 192.168.105.200:80;
# 主机名称
server_name 192.168.105.200;
# 日志的存放路径
access_log logs/server1.access.log combined;
location / {
# 默认首页文件
index index.html index.htm;
# 网页存放的目录
root /data0/htdocs/server1;
}
}
# 第二个虚拟主机
server {
# 监听的ip和端口
listen 192.168.105.201:80;
# 主机名称
server_name 192.168.105.201;
# 日志的存放路径
access_log logs/server2.access.log combined;
location / {
# 默认首页文件
index index.html index.htm;
# 网页存放的目录
root /data0/htdocs/server2;
}
}
# 第三个虚拟主机
server {
# 监听的ip和端口
listen 192.168.105.202:80;
# 主机名称
server_name 192.168.105.202;
# 日志的存放路径
access_log logs/server3.access.log combined;
location / {
# 默认首页文件
index index.html index.htm;
# 网页存放的目录
root /data0/htdocs/server3;
}
}
2、基于域名的虚拟主机
基于域名的虚拟主机是最常见的一种虚拟主机。只需配置你的 DNS 服务器,将每个主机名映射到正确的IP地址,然后配置Nginx服务器,令其识别不同的主机名就可以了。这种虚拟主机技术,使很多虚拟主机可以共享同一个P地址,有效解决了IP地址不足的问题。所以,如果没有特殊要求使你必须用一个基于IP的虚拟主机,最好还是使用基于域名的虚拟主机
# 第一个虚拟主机
server {
# 监听的ip和端口
listen 80;
# 主机名称
server_name aaa.domain.com;
# 日志的存放路径
access_log logs/aaa.domain.com.access.log combined;
location / {
# 默认首页文件
index index.html index.htm;
# 网页存放的目录
root /data0/htdocs/aaa.domain.com;
}
}
# 第二个虚拟主机
server {
# 监听的ip和端口
listen 80;
# 主机名称
server_name bbb.otherdomain.com;
# 日志的存放路径
access_log logs/bbb.otherdomain.com.access.log combined;
location / {
# 默认首页文件
index index.html index.htm;
# 网页存放的目录
root /data0/htdocs/bbb.otherdomain.com;
}
}
# 第三个虚拟主机
server {
# 监听的ip和端口
listen 80;
# 主机名称
server_name www.domain.com domain.com *.domain.com;
# 日志的存放路径
access_log logs/bbb.domain.com.access.log combined;
location / {
# 默认首页文件
index index.html index.htm;
# 网页存放的目录
root /data0/htdocs/domain.com;
}
}
日志
在nginx中与日志相关的有access_log(指定日志存放的位置、格式、缓存大小) log_format(日志的格式)两个
这两条指令可以在http{}模块下,也可以在server{}模块下。
1、用log_format指定格式
语法:log_formate name format [format ......] name是唯一的,不能重复
注意:log_format有一个默认格式,相当于Apache的combined日志格式
log_format combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$httpd_referer" "$http_user_agent"'
如果将nginx作为web服务器,其进行反向代理后,web服务器就不能查看客户端的真实IP了,因此需要自定义一些日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
$remote_addr和$http_x_forwarded_for用于记录IP地址
$remote_user用于记录远程客户端用户名称
$time_local用于记录访问时间与时区
$request 用于记录请求URL与HTTP协议
$ status 用于记录请求状态
$body_bytes_sent用于记录发送给客户端的文件主体内容大小
$$http_referer用于记录是从哪个页面链接访问过来的
$http_user_agent用于记录客户端浏览器的相关信息
2、access_log
语法:access_log 路径 log_format格式
access_log off; 关闭日志
access_log /data/logs/nginx.log; 默认日志
access_log /data/logs/nginx.log combined; 默认日志
access_log /data/logs/nginx.log main; 自定义日志
access_log /data/logs/nginx.log main buffer=32k; 自定义日志并设置内存缓冲区大小
注意:日志存放位置还可以用变量表示,如/data/logs/$server_name.log
假设server_name 指令设置的虚拟主机名称为test.domain.com,那么access_log 指令将把访问日志记录在/data/logs/test.domain.com.log 文件中。
(1)使用变量创建的文件位置,Nginx进程设置的用户和组必须有对该路径创建文件的权限。否则日志文件将不被创建。
(2)缓冲将不会被使用
(3)对于每一条日志记录,日志文件都将先打开文件,再写入日志记录,然后马上关闭。为了提高包含变量的日志文件存放路径的性能,须要使用open_log_file_cache指令设置经常被使用的日志文件描述符缓存。
open_log_file_cache指令主要用来设置含有变量的日志路径的文件描述符缓存,语法如下:
open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time] | off
该指令默认是禁止的,等同于 open_log_file_cache off
日志文件的切割
生产环境中的服务器,由于访问日志文件增长速度非常快,日志太大会严重影响服务器效率。同时,为了方便对日志进行分析计算,须要对日志文件进行定时切割。定时切割的方式有按月切割、按天切割、按小时切割等。最常用的是按天切割。
# vim cut_nginx_log.sh
#!/bin/bash
#这个脚本在每天00:00执行
#nginx日志存放的路径
logs_path="/usr/local/nginx/logs"
nginx_logs_path="/usr/local/nginx/logs/nginx"
mkdir -p $nginx_logs_path/`date | cut -d" " -f6`/`date | cut -d" " -f2`/
mv $logs_path/access.log $nginx_logs_path/`date | cut -d" " -f6`/`date | cut -d" " -f2`/`date | cut -d" " -f3`.log
nginx -s reopen
# crontab -e
00 00 * * * /bin/bash /usr/local/nginx/sbin/cut_nginx_log.sh
这个shell脚本和crontab配置主要实现的功能为:假设今天的日期为2023年5月19日,Nginx当前的日志文件为/usr/local/nginx/logs/access.log,2023年5月20日00:00会执行cut_nginx_log.sh脚本,cut_nginx_log.sh脚本首先创建一个目录/usr/local/nginx/logs/nginx/2023/05,然后将/usr/local/nginx/logs/access.log 文件移动并重命名为/usr/local/nginx/logs/nginx/2009/05/19.log,再重启Nginx主进程号告诉Nginx重新生成一个/usr/local/nginx/logs/access.log 文件,2009年5月20日的日志记录在这个新生成的日志文件中。而/usr/local/nginx/logs/nginx/2023/05/19.log 文件,就是2023年5月19日的日志文件。
压缩输出配置----gzip
目前,90%的浏览器都支持gzip和deflate两种压缩格式。如果浏览器支持gzip 压缩,就会在HTTP请求头中发送一行
“Accept-Encoding: gzip, deflate”,这时候Nginx服务器可以输出经过gzip压缩后的页面给浏览器,浏览器再解压。这种方式可以将网络线路上传输的大量数据消减60%以上,不仅节省了服务器带宽,同时加速了用户的下载速度和体验。
1、gzip指令
语法:gzip on|off
默认值:off
该指令用于开启或关闭gzip模块
2、gzip_buffers指令
语法:gzip_buffers number size
默认值:gzip_buffers 4 4K/8K
设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流.例如4 4k代表以4k为单位,按照原始数据大小以4k为单位的4倍申请内存.48k代表以8k为单位,按照原始数据大小以8k为单位的4倍申请内存.
如果没有设置,默认值是申请跟原始数据相同大小的内存空间去存储gzip压缩结果。
3、gzip_comp_level指令
语法:gzip_comp_level 1..9
默认值:zip_comp_level 1
压缩比越大,传输速度越快,消耗的cpu资源越高
4、gzip_min_length指令
语法:gzip_min_length length
默认值:gzip_min_length 0
建议设置为1k 即gzip_min_length 1024
5、gzip_http_version指令
语法:gzip_http_version 1.0|1.1
默认值:gzip_http_version 1.1
21世纪绝大多数的浏览器支持gzip,选择默认即可。
6、gzip_proxied指令
语法:gzip_proxied [off|expired|no-cache|no-store|private|no_last_modified|no_etag|auth|any]
默认值:gzip_proxied off
nginxz作为反向代理的时候开启,开启或关闭后端服务器返回的结果。匹配的前提是后端服务器必须要返回包含“Via”的header头。
off———关闭所有的代理结果数据的压缩。
expired——启用压缩,如果header头中包含“Expires”头信息。
no-cache——启用压缩,如果 header头中包含“Cache-Control:no-cache”头信息。
no-store—一启用压缩,如果header头中包含“Cache-Control:no-store”头信息。
private-----启用压缩,如果 header头中包含“Cache-Control:private”头信息。
no_last_modified———启用压缩,如果header头中不包含“Last-Modified”头信息。
no_etag———启用压缩,如果header头中不包含“ETag”头信息。
auth-—启用压缩,如果header头中包含“Authorization”头信息。
any—无条件启用压缩。
7、gzip_types指令
语法:gzip_types mime-type [mime-type...]
默认值:gzip_types text/html
匹配mime类型进行压缩,(无论是否指定)“text/html”类型总是会被压缩的。
注意:如果作为http server来使用,主配置文件中要包含文件类型配置文件。
http
{
include conf/mime.types;
......
}
例子:压缩常规文件
http
{
include conf/mime.types;
gzip on;
gzip_min_length 1024;
gzip_buffers 4 8k;
gzip_http_version 1.1;
gzip_types text/plain application/x-javascript text/css text/html application/xml;
}
nginx的自动列目录
实现类似页面
前提条件:不能有index指令设置的默认首页文件
location
{
autoindex on;
}
还有两个与自动列目录相关的指令:
autoindex_exact_size [on|off] 设定索引时文件大小的单位(B、KB、MB、GB)
autoindex_localtime [on|off] 开启以本地时间来显示文件时间的功能。默认是关
浏览器本地缓存设置
expires指令
语法:expires [time|epoch|max|off]
默认值:expires off
例:对常见格式的图片、Flash文件在浏览器本地缓存30天,对js、css 文件在浏览器本地缓存1小时,如代码3-10所示。
location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}
location ~ .*.(js|css)$
{
expires 1h;
}
4、Nginx与PHP(FastCGI)的安装、配置与优化
CGI和FastCGI介绍
1、nginx作为web服务器,并不能直接处理静态、动态请求。
2、cgi解释器,由于每次处理请求后,其都会关闭,导致速度极慢,因此出现了FastCGI
3、FastCGI读取php.ini,启动多个CGI(保存在内存中),等待客户端的请求,并分配CGI
Nginx+FastCGI工作原理
所有的外部程序都要通过FastCGI来调用,其在Linux下是socket,(这个socket可以是文件socket,可以是ip socket).为了调用CGI,还需要warpper(启动一个程序的程序)。当请求发送到nginx时,socket接受后,通过FastCGI接口让wrapper启动CGI,然后调用application.
spawn-fcgi与php-fpm
这两个就是支持php的FastCGI进程管理器
spawn-fcgi是httpd服务器lighttpd的一部分,目前已经独立为一个项目,一般与lighttpd配合使用来支持php.但是由于lighttpd的spawn-fcgi在高并发访问时,会出现内存泄漏甚至重启FastCGI的问题。因此我们不选择它。
php-fpm是作为php的一个补丁来开发的,在安装时需要和php源码一起编译(它被编译到php的内核中),因此在性能方面高于spawn-fcgi,因此我们选择nginx+php-fpm.
nginx主要功能:处理静态请求、转发动态请求
php/php-fpm主要功能:解析php动态请求
因此我们通常选择将它们部署在不同的服务器上。
php与php-fpm的安装与优化
1、下载安装包
www.php.net php-5.2.13.tar.gz
http://php-fpm.org/downloads/ php-5.2.13-fpm-0.5.13.diff.gz
2、配置安装环境
# yum install gcc gcc-c++ libxml2 libxml2-devel autoconf libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel zlib zlib-devel glibc glibc-devel glib2 glib2-devel gzip patch -y
3、编译安装PHP和PHP-FPM
解压php并将php-fpm加入
# tar zxvf php-5.2.13.tar.gz
# gzip -cd php-5.2.13-fpm-0.5.13.diff.gz | patch -d php-5.2.13 -p1
解决问题
# curl -o php-5.2.13.patch https://mail.gnome.org/archives/xml/2012-August/txtbgxGXAvz4N.txt
# cd php-5.2.13
# patch -p0 -b < ../php-5.2.13.patch
patching file ext/dom/node.c
Hunk #1 succeeded at 1950 (offset 55 lines).
patching file ext/dom/documenttype.c
Hunk #1 succeeded at 215 (offset 10 lines).
patching file ext/simplexml/simplexml.c
Hunk #1 succeeded at 1340 (offset -77 lines).
编译安装
# ./configure --prefix=/usr/local/src/php --enable-fastcgi --enable-fpm
# make && make install
# cp php.ini-dist /usr/local/src/php/lib/php.ini
--enable-fastcgi”是启用对PHP的FastCGI支持,“--enable-fpm”是激活对FastCGI模式的fpm支持
4.配置与优化PHP-FPM
php全局配置文件:/usr/local/src/php/lib/php.ini
php-fpm引擎的配置文件: /usr/local/src/php/etc/php-fpm.conf
标签listen_address是配置fastcgi进程监听的IP地址以及端口,默认是127.0.0.1:9000。
127.0.0.1:9000
标签display_errors用来设置是否显示PHP错误信息,默认是0,不显示错误信息,设置为1可以显示PHP错误信息。
0
标签user和group用于设置运行FastCGI进程的用户和用户组。需要注意的是,这里指定的用户和用户组要和Nginx配置文件中指定的用户和用户组一致。
nobody
nobody
标签max_children用于设置FastCGI的进程数。根据官方建议,小于2GB内存的服务器,可以只开启64个进程,4GB以上内存的服务器可以开启200个进程。
5
标签request_terminate_timeout用于设置FastCGI执行脚本的时间。默认是0s,也就是无限执行下去,可以根据情况对其进行修改。
0s
标签rlimit_files用于设置PHP-FPM对打开文件描述符的限制,默认值为1024。这个标签的值必须和Linux内核打开文件数关联起来,例如要将此值设置为65535,就必须在Linux命令行执行'ulimit -HSn 65536'。
1024
标签max_requests指明了每个children最多处理多少个请求后便会被关闭,默认的设置是500。
500
标签allowed_clients用于设置允许访问FastCGI进程解析器的IP地址。如果不在这里指定IP地址,Nginx转发过来的PHP解析请求将无法被接受。
127.0.0.1
index.php
server {
include port.conf;
server_name www.ixdba.net ixdba.net;
location / {
index index.html index.php;
root /web/www/www.ixdba.net;
}
location ~ .php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME html$fastcgi_script_name;
include fastcgi_params;
}
}
5、Nginx HTTP 负载均衡和反向代理的配置与优化
负载均衡与反向代理
随着网站访问量的快速增长,单台服务器已经无法承担大量用户的并发访问,必须采用多台服务器协同工作,以提高计算机系统的处理能力和计算强度,满足当前业务量的需求。而如何在完成同样功能的多个网络设备之间实现合理的业务量分配,使之不会出现一台设备过忙、而其他的设备却没有充分使用的情况。要解决这一问题,可以采用负载均衡的方法
负载均衡
负载均衡是由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,都可以单独对外提供服务而无须其他服务器的辅助。通过某种负载分担技术,将外部发送来的请求均匀分配到对称结构中的某一台服务器上,而接收到请求的服务器独立地回应客户的请求。均衡负载能够平均分配客户请求到服务器阵列,藉此快速获取重要数据,解决大量并发访问服务问题。这种群集技术可以用最少的投资获得接近于大型主机的性能
反向代理
反向代理(Reverse Proxy)是指以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给Internet 上请求连接的客户端,此时代理服务器对外就表现为一个服务器。
通常的代理服务器,只用于代理内部网络对Internet的连接请求,客户机必须指定代理服务器,并将本来要直接发送到Web服务器上的http请求发送到代理服务器中。由于外部网络上的主机并不会配置并使用这个代理服务器,普通代理服务器也被设计为在Internet上搜寻多个不确定的服务器,而不是针对Internet上多个客户机的请求访问某一个固定的服务器,因此普通的Web代理服务器不支持外部对内部网络的访问请求。当一个代理服务器能够代理外部网络上的主机访问内部网络时,这种代理服务的方式称为反向代理服务。此时代理服务器对外就表现为一个Web服务器,外部网络就可以简单把它当作一个标准的Web服务器而不需要特定的配置。不同之处在于,这个服务器没有保存任何网页的真实数据,所有的静态网页或CGI程序,都保存在内部的Web服务器上。因此对反向代理服务器的攻击并不会使网页信息遭到破坏,这样就增强了Web服务器的安全性。
常见负载均衡方法
1、用户手动选择
2、DNS轮询
在域名解析中添加A记录即可
优点:成本低廉
缺点:
可靠性低
当一台服务器发生故障时,所有访问该服务器的请求不会被响应。同时各地宽带、路由器等许多NDS都有缓存,导致一段时间不能访问故障服务器。
负载分配不均衡
由于轮询算法太过简单,不能为性能较好的分配更多请求,造成资源浪费。由于DNS缓存的存在,一段时间只会访问同一机器。
4、四/七层负载均衡设备
四层:lvs
七层:nginx
tcp/ip七层网络模型
常见四/七层负载均衡交换机:F5 BIG-IP、Citrix、NetScaler、Radware、Cisco CSS、Foundry
F5 BIG-IP使用较多。
如下图是 F5 BIG-IP实现动、静态网页分离的负载均衡架构图
(1)如图,假设域名blog.s135.com 被解析到F5的外网/公网虚拟IP:61.1.1.3 (vs_squid),该虚拟IP下有一个服务器池(pool_squid),该服务器池下包含两台真实的 Squid服务器( 192.168.1.11和192.168.1.12)
(2)如果Squid缓存未命中,则会请求F5的内网虚拟IP: 192.168.1.3 (vs_apache),该虚拟IP下有一个默认服务器池(pool_apache_default),该服务器池下包含两台真实的Apache服务器(192.168.1.21和192.168.1.22),当该虚拟IP匹配 iRules规则时,则会访问另外一个服务器池( pool_apache_irules),该服务器池下同样包含两台真实的 Apache 服务器(192.168.1.23和192.168.1.24)XXXXXX
(3)另外,所有真实服务器的默认网关指向F5的自身内网IP,即192.168.1.2
(4)所有的真实服务器通过SNATIP地址61.1.1.4访问互联网
实际案例
Nginx负载均衡与反向代理实现动、静态网页分离
动、静态网页分离,就是让动态PHP等程序网页去访问PHP Web服务器,让缓存页、图片、JavaScript、Css、Flash去访问Squid等缓存服务器
Nginx负载均衡的HTTP Upstream模块
Upstream模块是Nginx负载均衡的主要模块,它提供了一个简单方法来实现在轮询和客户端IP之间的后端服务器负载均衡,并可以对后端服务器进行健康检查。
upstream backend{
server backend1.example.com weight=5;
server baskend2.example.com:8080;
server unix:/tmp/backend3;
}
server{
location /{
proxy_pass http://backend;
}
}
ip_hash指令
当对后端的多台动态应用服务器做负载均衡时,ip_hash指令能够将某个客户端IP的请求通过哈希算法定位到同一台后端服务器上。
注意:如果要对使用了ip_hash的服务器摘除一段时间,必须将其标记为down
upstream backend{
ip_hash;
server backend1.ac.com;
server baskend2.ac.com;
server baskend3.ac.com down;
server baskend4.ac.com;
}
若不这样做,nginx会以3台机器重新分配,可能导致之前客户端ip_hash到其它服务器上(session不一致)
所以能用session共享就不用ip_hash
server指令的参数
server指令
后面接域名、IP、端口号、UNIX Socket
参数
weigth=数字 数值越高,权重值越高,分配到的请求数越多(默认为1)
max_fails=数字 在fail_timeout指定的时间内对后端服务器请求失败的次数(默认值为1,设置为0表示关闭)
fail_timeout=时间 在经历max_fails设置的失败次数后,暂停的时间
down 标记服务器为永久离线,用于ip_hash指令
backup 仅在非backup服务器全部宕机或繁忙的时候才启用
upstream backend{
server backend1.ac.com weight=5;
server 127.0.0.1:8088 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend;
}
负载均衡器的双机高可用
方案一:主服务器绑定公网虚拟ip,当主服务器宕机后,热备服务器接管公网虚拟ip
方案二:主服务器和热备服务器都绑定一个公网虚拟ip,当主服务器宕机后,还是能够提供服务
优缺点:方案一会有一台机器处于空闲状态,方案二会占用两个公网ip。一般来说选择方案一
方案一:
(1)域名www.test.com绑定到虚拟ip 61.1.1.2上
(2)主机绑定61.1.1.2
# /sbin/ipconfig eth0:1 61.1.1.2 broadcast 61.1.1.255 netmask 255.255.255.0 up
# /sbin/route add -host 61.1.1.2 dev eth0:1
# /sbin/arping -I eth0 -c 3 -s 61.1.1.2 61.1.1.1
(3)此时访问61.1.1.2其实是访问61.1.1.4,slave机器处于空闲状态
(4)master宕机后,slave会在几秒内接管虚拟ip 61.1.1.2,与自己绑定并发送ARPing包给IDC的公网网关刷新MAC地址
# /sbin/ipconfig eth0:1 61.1.1.2 broadcast 61.1.1.255 netmask 255.255.255.0 up
# /sbin/route add -host 61.1.1.2 dev eth0:1
# /sbin/arping -I eth0 -c 3 -s 61.1.1.2 61.1.1.1
(5)此时访问61.1.1.2其实是访问61.1.1.5
方案一还可以用基于VRRP路由协议的Keepalived软件来实现
方案二:
(1)域名www.test.com通过DNS轮询绑定到公网虚拟ip 61.1.1.2、61.1.1.3上
机器1
# /sbin/ipconfig eth0:1 61.1.1.2 broadcast 61.1.1.255 netmask 255.255.255.0 up
# /sbin/route add -host 61.1.1.2 dev eth0:1
# /sbin/arping -I eth0 -c 3 -s 61.1.1.2 61.1.1.1
机器2
# /sbin/ipconfig eth0:1 61.1.1.3 broadcast 61.1.1.255 netmask 255.255.255.0 up
# /sbin/route add -host 61.1.1.3 dev eth0:1
# /sbin/arping -I eth0 -c 3 -s 61.1.1.2 61.1.1.1
(3)此时访问www.test.com实际上是根据DNS轮询访问61.1.1.4、61.1.1.5
(4)机器1宕机后,机器2会在几秒内接管虚拟ip 61.1.1.2,与自己绑定并发送ARPing包给IDC的公网网关刷新MAC地址,此时机器2有61.1.1.2和61.1.1.3两个公网ip
机器2
# /sbin/ipconfig eth0:1 61.1.1.2 broadcast 61.1.1.255 netmask 255.255.255.0 up
# /sbin/route add -host 61.1.1.2 dev eth0:1
# /sbin/arping -I eth0 -c 3 -s 61.1.1.2 61.1.1.1
(5)此时访问www.test.com其实是根据DNS轮询访问61.1.1.2、61.1.1.3也就是访问61.1.1.5。如下图:
我们可以利用脚本来实现上述的自动故障转移
nginx_dual_high_availability1.sh
nginx_dual_high_availability2.sh
后台运行即可
nohup /bin/bash ./nginx_dual_high_availability1.sh > /dev/null 2>&1 &
nohup /bin/bash ./nginx_dual_high_availability2.sh > /dev/null 2>&1 &
6、Nginx的Rewrite规则
rewrite基础
rewrite主要功能就是实现URL的重写,nginx的rewrite规则采用pcre perl正则表达式的语法进行规则匹配。要使用nginx的该功能,必须编译安装PCRE库
语法:rewrite 正则表达式 跳转地址 结尾标识符
rewrite在server、location、if中均可使用
结尾标识符:last(表示完成rewrite规则)、break(本规则完成后终止匹配)、redirect(临时重定向)、permanent(永久重定向)
last、break实现URL重写,浏览器地址栏url不变,redirect、permanent实现URL跳转,浏览器地址栏url改变
last表示在执行完本条rewrite规则后,会对其所在的server{...}标签重新发起请求(使用alias指令必须用last)
break表示在执行完本条rewrite规则后,终止匹配(使用proxy_pass必须用break,否则可能会导致死循环)
如:
location /cms/ {
proxy_pass http://test.domain.com;
rewrite "^/cms/(.*).html" /cms/index.html break;
}
该例子只能用break,因此在根location中用last,在非根用break
rewrite指令
return指令:用于结束规则的执行并返回状态码给客户端
rewrite指令:根据表达式重定向URL
例子1:将/photos/123456重定向到/path/to/photos/12/1234/123456.png(出现()[]{}等最好用引号括起来)
# rewrite "/photos/([0,9] {2})([0,9] {2})([0,9] {2})" /path/to/photos/$1/$1$2/$1$2$3.png
例子2:访问http://www.yourdomain.com/test?id=5经过301后跳转到http://www.yourdomain.com/home
# rewrite "^/test(.*)" http://www.yourdomain.com/home? permanent;
set指令:用于定义一个变量,并给变量赋值
# set $hostname 'mysql';
全局变量:
$args $content_length $content_type $document_root $document_uri $host $http_user_agent $http_cookie $limit_rate $request_body_file $request_method
$remote_addr等等
if指令
该指令用于检查一个条件是否符合,如果条件符合,则执行大括号内的语句.if指令不支持嵌套,不支持多个条件&&和ll处理
HTTP状态码
100~199 消息:这一类型的状态码,代表请求已被接受,需要继续处理。
100:Continue 客户端应当继续发送请求,这个临时响应是用来通知客户端它的部分请求已经被服务器接收,且仍未被拒绝。客户端应当继续发送请求的剩余部分
101:Switching Protocols 服务器已经理解了客户端的请求,并将通过Upgrade消息头通知客户端采用不同的协议来完成这个请求
102:Processing 由WebDAV扩展的状态码,代表处理将被继续执行
200~299 成功:这一类型的状态码,代表请求已成功被服务器接收、理解、并接受。
201:Created 表示请求已经被成功处理,并且创建了新的资源
202:Accepted 服务器已接受请求,但尚未处理
203:Non-Authoritative Information 服务器已成功处理了请求,但返回的实体头部元信息不是在原始服务器上有效的确定集合,而是来自本地或者第三方的拷贝
204:No Content 服务器成功处理了请求,但不需要返回任何实体内容,并且希望返回更新了的元信息
205:Reset Content 服务器成功处理了请求,且没有返回任何内容。但是与204响应不同,返回此状态码的响应要求请求者重置文档视图
206:artial Content 服务器已经成功处理了部分 GET 请求
207:Multi-Status 由WebDAV(RFC 2518)扩展的状态码,代表之后的消息体将是一个XML消息,并且可能依照之前子请求数量的不同,包含一系列独立的响应代码
300~399 重定向:这类状态码代表需要客户端采取进一步的操作才能完成请求
301:Moved Permanently 永久重定向,表示资源已经永久移动到另一个位置
302:Move Temporarily 临时重定向,表示资源临时移动到了另一个位置
305:Use Proxy 被请求的资源必须通过指定的代理才能被访问
307:Temporary Redirect 请求的资源临时从不同的URI 响应请求
400~499 错误:这类的状态码代表了客户端看起来可能发生了错误,妨碍了服务器的处理
400:Bad Request 语义有误,当前请求无法被服务器理解或请求参数有误
401: Unauthorized 当前请求需要用户验证
402: Payment Required 该状态码是为了将来可能的需求而预留的
403:Forbidden 服务器已经理解请求,但是拒绝执行它。与401响应不同的是,身份验证并不能提供任何帮助,而且这个请求也不应该被重复提交
405:Method Not Allowed 请求行中指定的请求方法不能被用于请求相应的资源
406: Not Acceptable 请求的资源的内容特性无法满足请求头中的条件,因而无法生成响应实体。
407:Proxy Authentication Required 与401响应类似,只不过客户端必须在代理服务器上进行身份验证
408:Request Timeout 请求超时
409:Conflict 由于和被请求的资源的当前状态之间存在冲突,请求无法完成
410: Gone 被请求的资源在服务器上已经不再可用,而且没有任何已知的转发地址
500~699 服务器错误:这类状态码代表了服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理
500 Internal Server Error 服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。一般来说,这个问题都会在服务器端的源代码出现错误时出现。
501 Not Implemented 服务器不支持当前请求所需要的某个功能
502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应
503 Service Unavailable 由于临时的服务器维护或者过载,服务器当前无法处理请求
504 Gateway Timeout 作为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器(URI标识出的服务器,例如HTTP、FTP、LDAP)或者辅助服务器(例如DNS)收到响应。
505 HTTP Version Not Supported 服务器不支持,或者拒绝支持在请求中使用的 HTTP 版本。这暗示着服务器不能或不愿使用与客户端相同的版本。响应中应当包含一个描述了为何版本不被支持以及服务器支持哪些协议的实体。
506 Variant Also Negotiates 代表服务器存在内部配置错误:被请求的协商变元资源被配置为在透明内容协商中使用自己,因此在一个协商处理中不是一个合适的重点。
507 Insufficient Storage 服务器无法存储完成请求所必须的内容
509 Bandwidth Limit Exceeded 服务器达到带宽限制。这不是一个官方的状态码,但是仍被广泛使用。
510 Not Extended 获取资源所需要的策略并没有被满足
600 Unparseable Response Headers 源站没有返回响应头部,只返回实体内容
nginx模块开发
类型
Handlers(处理模块):发送文件或转发请求时
Filters(过滤模块):把输出压缩或在服务端添加一些东西时
Load-balancers(负载均衡模块):选择一台后端服务器将HTTP请求发送出去
模块处理流程:客户端发送HTTP请求到Nginx服务器-->Nginx基于配置文件中的位置选择一个合适的处理模块-->负载均衡模块选择一台后端服务器-->处理模块进行处理并把输出缓冲放到第一个过滤模块上-->第一个过滤模块处理后输出给第二个过滤模块-->......-->第N个过滤模块-->最后将结果发送给客户端
HelloWorld模块编写
ngx_http_hello_world_module.c
config