进程间通信的机制——信号量。为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域。临界区域是指执行数据更新的代码需要独占式地执行。而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在访问它,也就是说信号量是用来调协进程对共享资源的访问的。
Kill -信号选项 nginx主进程号
TERM/INT 迅速关闭进程
QUIT 优雅的关闭进程,即等请求结束后再关闭
HUP 改变配置文件,平滑的重读配置文件,中间不断线,当所有请求结束时才重新加载配置文件
USR1 重读日志,在日志按月/日分割时有用(当你将日志重命名后日志还是会增加因为linux文件系统inode相同)
USR2 平滑的升级(升级nginx)当你启动新的nginx时,当旧的进程USR2掉,就会自动过渡到新Nginx进程
WINCH 优雅关闭旧的进程(配合USR2来进行升级)
不查进程号进行平滑加载配置文件技巧:kill -HUP `more /usr/local/nginx/logs/nginx.pid`
平滑重载日志文件技巧:
kill -USR1 `more /usr/local/nginx/logs/nginx.pid`
二、配置虚拟主机
Nginx配置片段解释
#
全局区
worker_processes 1 #工作进程个数,太大会争夺CPU,一般设置为CPU数*核数
server_tokens off; #隐藏Nginx版本号
event {
#一般是配置Nginx连接特性
worker_connections 1024; 一个子进程能同时允许
最大
1024个连接,这个值的大小需要根据系统配置决定
}
http {
#配置http服务器
server {
#虚拟主机
listen 80;
server_name gxd.com;
....
location { #
定位,把特殊的路径或文件再次定位,如.php文件单独处理,image目录单独处理
}
}
}
三、日志
server
{
access_log logs/host.access.log main; #为了便于区分最好以网站名起日志名字
#访问日志,main格式是一种日志格式,包含了ip,响应状态,http请求方式,请求头referer,user_agent(
访问网站使用的浏览器类型、系统,如果你检查日志没有标识浏览器类型此项则有可能是蜘蛛
)
}
#日志格式可以自己配置,它主要是几个变量,你可以随便拼接,在配置文件中搜索log_format你就会发现
#如果服务器访问量突然增加,不要高兴,有可能是蜘蛛或攻击,这时需要
检查
日志IP是否是同一个或几个。
#你会发现日志太大连编辑器都打不开,这时需要日志切割
日志切割:
1、根据时期切割
编写sh:vi runSpliteLog.sh
四、location匹配#!/bin/shLOGPATH=/usr/local/nginx/logs/gxd.com.access.logBACKUPDIR=/data/ $(date -d yesterday +%Y%m) #每月一个日志目录backupFile=$ BACKUPDIR/ $(date -d yesterday +%Y%m%d%H%M).gxd.com.access.logmkdir -p $ BACKUPDIR #创建目录mv $LOGPATH $backupFile #移走文件touch $LOGPATH #移走日志文件后再创建一个空的文件kill -USR1` cat /usr/local/nginx/logs/nginx.pid` #重载日志文件最后加入contab中,每天0时执行一次crontab -e
location = path{
#精确匹配,path=文件路径
}
location patt{
#一般匹配,正则。
}
location ~ patt{
#正则匹配
}
优先判断精确匹配,如果命中,则立即返回结果并结束解析过程,判断普通命中,如果有多个命中则取最长的匹配结果,然后继续判断正则匹配。
正则命中顺序是从后向前,最后一个生效
五、Rewrite
使用正则表达式重写URI(需PCRE库),并且可以根据相关变量重定向和选择不同的配置。
如果这个指令在server字段中指定,那么将在被请求的location确定之前执行,如果在指令执行后所选择的location中有其他的重写规则,那么它们也被执行。如果在location中执行这个指令产生了新的URI,那么location又一次确定了新的URI。这样的循环可以最多执行10次,超过以后nginx将返回500错误。
语法:
一个使用=或者!=运算符的比较语句。
·使用符号~*和~模式匹配的正则表达式:
·~为区分大小写的匹配。
·~*不区分大小写的匹配(firefox匹配FireFox)。
·!~和!~*意为“不匹配的”。
示例:
if($http_user_agent ~
msie
)
{
#set $client_type = IE #设置变量为IE,这个变量是在重写中有效,而不在php中$_SERVER中()
#return 403;#判断user_agent,如果是IE则403
#breake #停止重写
}
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
重写标记说明:
last - 完成重写指令,之后搜索相应的URI或location。
break - 完成重写指令。
redirect - 返回302临时重定向,如果替换字段用http://开头则被使用。
permanent - 返回301永久重定向。
五、PHP与Nginx
apache一般是把php当自己的一个模块来启动,而Nginx是把http请求转发给php独立进程(默认端口为9000)进行通信,称为fastcgi运行方式,因此apache编译的php不能用于Nginx。
1、fastcig是一种通信接口,是一种通信工具。它被很多语言所支持
2、php-fpm是一个fastcgi管理器,只用于php。
3、php与Nginx的默认通信方式是http,我们一般要用更多快的socket方式来通信,在高并发时socket方式效果显著。
我们应该将它们都改为socket方式连接
php-fpm、mysql、redis,这里只说下php-fpm
a)、创建socket文件,位置在/dev/shm(因为这个目录是个tmpfs,速度比磁盘快得多)
touch /dev/shm/php-fcgi.sock
chmod 777 /dev/shm/php-fcgi.sock
b)、vi /usr/local/php/etc/php-fpm.conf
;listen = 127.0.0.1:9000listen = /dev/shm/php-fcgi.sockc)、location ~ .*\.(php|php5)?$ {#fastcgi_pass 127.0.0.1:9000;fastcgi_pass unix:/dev/shm/php-fcgi.sock;fastcgi_index index.php;include fastcgi.conf;}
看配置文件中你会看到
fastcgi_pass 127.0.0.1:9000 #让9000端口去处理
fastcgi_param SCRIPT_FILENAME $document_root$fastcig_script_name
include fastcgi_params
六、gzip压缩
原理:浏览器----> 请求 ------>声明可以接受的gzip/deflate/sdch压缩
服务器----> 响应 ------> 把内容压缩------>发给浏览器
浏览器---->解压缩码
注意:图片媒体资源等二进制文件不必压缩,因为压缩比较小,白白浪费服务器资源
配置gzip:
server
{
gzip on|off #是否开启gzipgzip_buffers 32 4K #缓冲多少块,缓冲每块多大小gzip_comp_level #压缩级别,一般用6,与服务器资源成正比gzip_deisable #正则匹配URI不进行压缩gizp_min_length #超过这个值的大小才进行压缩,因为太小压缩效果不好反而浪费资源,有可能3kb的东西压缩后反而长到100KB,因为压缩文 件有一些自带的数据gzip_http_version #1.0/1.1 选择压缩的http版本,现在都全是1.1,可以不设置这玩意gzip_proxied #对请求代理服务器缓存内容gzip_types text/plain applicate/xml #对哪些文件进行压缩MIME类型,如txt,xml,html,cssgzip_var on/off #是否传输gzip压缩标志
实验:将meilele.com的首页文件保存到本地,发现请求时未开启前是342kb,开启压缩后是67.9kb。压缩率极高。
七、expires 缓存
Expires字段声明了一个网页或URL地址不再被浏览器缓存的时间,一旦超过了这个时间,浏览器都应该联系原始服务器。如果取浏览器缓存资源则请求会返回304。该技术一般用在静态资源上。服务器响应头包含有Cache-control和Expires字段
304 - Not Modified 资源未被修改,此时浏览器会优先取缓存中的数据。原理:如果浏览器中有缓存该资源,则在请求的header中会带上:If-Modified-Since:时间和If-None-Math:编号;当服务器收到请求后会根据If-None-Math编号与资源修改时间等计算出的编号作对比,如果相同,则会在response headers中返回Etag和Last-Modified,返回状态304且不会返回主体信息;客户端发现是304,则就取缓存中数据。这个过程也请求了服务器,但是服务器只返回了部分头信息,没有主体。
配置示例:
location ~*\.(jpg|png|gif|css|js|swf)${
root html;
expires 3d; #s:秒,m:分,h:时,d:天
}
注意服务器时间要正确。过期时间是以服务器时间来设置的
八、反向代理
反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。
代理服务器+反向代理服务器(真正那台内容服务器)
a)、配置实例:
nginx+apache。
将php请求转发给另外一台服务器处理,静态资源由nginx负责,php由apache服务器负责,实现
动静分离
1、首先配置apache代理服务器
打开apache的mod_proxy和mod_http_proxy模块
2、打开nginx.conf,
location ~\.php$ {
proxy_pass http://www.jiajiayou.sinaapp.com:8080 #注意http://不能少
#这里的fastcgi_pass,fastcgi_index,fastcig_para,include等可以全部注释掉
}
b)、配置实例:
nginx+
nginx
直接配置即可
正向代理也就是传说中的代理,他的工作原理就像一个跳板,简单的说,我是一个用户,我访问不了某网站,但是我能访问一个代理服务器,这个代理服务器呢,他能访问那个我不能访问的网站,于是我先连上代理服务器,告诉他我需要那个无法访问网站的内容,代理服务器去取回来,然后返回给我。从网站的角度,只在代理服务器来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏了用户的资料,这取决于代理告不告诉网站。
反向代理正好相反,对于客户端而言它就像是原始服务器,并且客户端不需要进行任何特别的设置。客户端向反向代理的命名空间(name-space)中的内容发送普通请求,接着反向代理将判断向何处(原始服务器)转交请求,并将获得的内容返回给客户端,就像这些内容原本就是它自己的一样。
九、负载均衡
N台服务器平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况。那么负载均衡的前提就是要有多台服务器才能实现,也就是两台以上即可。
配置:
#首先定义一组服务器,并配置负载规则
up_stream phpServerGroup{
ip_hash; #表示根据Ip的hash值固定转发请求,这个保证某一个ip一定只访问到某一台服务器上,保证session一致
fair; #根据响应时间转发,响应时间短的优先转发请求
url_hash #第三方模块,根据url的hash来转发请求,有它后下面的服务器就不能再配置weigth权重了
server backend1.example.com weight=5
max_fails=3;
#注意这里不要写http://
#
weight=number 设置服务器权重,默认是1,表示轮训的机率,它的傎在整个组中越大几率就越大,主要用在服务器硬件不一致的情况下
#
max_fails=number 最大失败次数
#fail_timeout=time 请求失败后暂停请求它的时间
#back 作为备份服务器,只有当其它服务器都太忙时才会请求这台
#down 服务器不可用
#max_conns=number 最大连接次数,默认是0表示没有限制
#slow_start=time
#注意如果你什么标记也不配,则默认是逐个服务器进行请求。其中有一些其他第三方负载算法,比如:NginxHttpUpstreamConsistentHash
}
server {
location ~\.php$ {
proxy_pass http://phpServerGroup;
}
}
#注意:反向代理服务器拿到ip为代理服务器,如果才能保证反向代理服务器拿到客户机的ip呢?
server {
location ~\.php$ {
proxy_set_header X-Forwarded-For $remote_addr;
#设置到http头信息,注意这里是将remote_addr的值写过去,remote_addr是tcp中的地址而不是拿的客户http请求头的值,所以这里不存在伪造ip的风险
proxy_pass http://phpServerGroup;
}
}
十、大访问量优化思路
1、减少请求次数
a)、expires资源生命周期
b)、合并css背景图片
2、减少mysql查询,以及提高mysql语句质量
a)、使用redis、memcache等缓存减少查询
b)、优化SQL语句质量
3、利用CDN分离资源,减少服务器压力加速资源的请求速度
4、服务器集群+负载均衡
a)、数据库读写分离
b)、分布式缓存
十一、ab压力测试及nginx性能监控
ab语法:
-c 并发数
-n 请求次数
-k 长连接keep-alive
解决:socket:Too many open files
每一个请求都打开一个socket连接,并发太大就会报这个
ulimit -n 显示限制的socket最大数
ulimit -n 2000 设置为2000
添加统计模块Nginx的ngx_http_stub_status_module
安装:
进源码包nginx
make clean
./configure --prefix=/usr/local/nginx/ --add-module=/路径/ngx_http_consistent_hash-mater --with-http_stub_status_module
make && make install
配置模块:
location /status {
stub_status on;
access_log off;
allow 192.168.0.100;
deny all;
}
访问统计:localhost/status
十二、常规硬件配置下实现Nginx单机1万并发
1、检查error.log
2、检查demesg
思路:
1、socket
系统上:
a、最大连接数
1、打开Nginx配置文件,worker_connections 10000;
2、
查看最大值 :more /proc/sys/net/core/somaxconn
设置为5000:echo 50000 >
/proc/sys/net/core/somaxconn
b、洪水攻击:为了测试,取消洪水防御
查看是否开启:cat /proc/sys/net/ipv4/tcp_syncookies
关闭它:echo 0 >
/proc/sys/net/ipv4/tcp_syncookies
c、加快tcp连接回收
查看:cat /proc/net/ipv4/tcp_tw_recycle
设置为开启 echo 1 >
/proc/net/ipv4/tcp_tw_recycle
d、空的tcp连接是否回收利用
查看:cat /proc/net/ipv4/tcp_tw_reuse
设置为开启 echo 1 >
/proc/net/ipv4/tcp_tw_reuse
注意:为了每次开机使用此配置,我们可以写一个shell,开机启动
nginx上:
a、子进程允许打开的连接
打开配置文件在全局区加入:worker_rlimit_nofiles 10000;
b、高并发下关闭keep-alive,将其设置为0,或者改小到2秒,太长时间会白白占用连接不干事,
在高并发
非常浪费资源。
2、文件
a、
将操作系统最大进程调大到2万 ulimit -n 20000