LNMP架构(三)
Nginx负载均衡
负载均衡 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。负载均衡,英文名称为Load Balance,其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。
如何配置负载均衡呢?借助一个模块叫做upstream,可以在该模块下可以定义多个IP和端口。
现在借助qq.com来做个演示,如何知道qq.com的IP呢?可以用命令dig,没找到命令安装bind-utils包。
[[email protected] ~]# yum install -y bind-utils
获取qq.com的IP,其实就是域名解析。
[[email protected] ~]# dig qq.com ; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> qq.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31325 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;qq.com. IN A ;; ANSWER SECTION: qq.com. 394 IN A 111.161.64.48 qq.com. 394 IN A 111.161.64.40 ;; Query time: 53 msec ;; SERVER: 119.29.29.29#53(119.29.29.29) ;; WHEN: 日 7月 08 20:26:44 CST 2018 ;; MSG SIZE rcvd: 67
拿这2个IP来做负载均衡,配置文件
[[email protected] ~]# vim /usr/local/nginx/conf/vhost/load.conf
配置内容
upstream qq ##upstream模块,qq可以是任何名字 { ip_hash; ##在多台服务器提供同一个服务的时候,支持用户始终登录到A服务器上,避免登录到B机器上导致没有在B机器上输入过密码登录不成功。 server 111.161.64.48:80; ##如果是80,那么:80可以省略掉。 server 111.161.64.40:80; } server { listen 80; server_name www.qq.com; location / { proxy_pass http://qq; ##http://后面跟上面起的名字qq。 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
保存退出,在未加载配置前
[[email protected] vhost]# curl -x127.0.0.1:80 www.qq.com
会访问到默认虚拟主机默认页
加载配置后,就会访问到QQ的真正主页去。
[[email protected] vhost]# /usr/local/nginx/sbin/nginx -t [[email protected] vhost]# /usr/local/nginx/sbin/nginx -s reload [[email protected] vhost]# curl -x127.0.0.1:80 www.qq.com
注意:Nginx不支持代理https,即是443端口;如果用户要登录https,只能通过代理服务器(https)访问web服务器的http(即80端口),间接达到访问443(https)。
ssl原理
浏览器发送一个https的请求给服务器;
服务器要有一套数字证书,可以自己制作(后面的操作就是阿铭自己制作的证书),也可以向组织申请,区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出>提示页面,这套证书其实就是一对公钥和私钥;
服务器会把公钥传输给客户端;
客户端(浏览器)收到公钥后,会验证其是否合法有效,无效会有警告提醒,有效则会生成一串随机数,并用收到的公钥加密;
客户端把加密后的随机字符串传输给服务器;
服务器收到加密随机字符串后,先用私钥解密(公钥加密,私钥解密),获取到这一串随机数后,再用这串随机字符串加密传输的数据(该加密为对称加密,所谓对称加密,就是将数据和私钥也就是这个随机字符串>通过某种算法混合在一起,这样除非知道私钥,否则无法获取数据内容);
服务器把加密后的数据传输给客户端;
客户端收到数据后,再用自己的私钥也就是那个随机字符串解密;
生成ssl**对
生成**需要工具,生成的**放到/usr/local/nginx/conf路径下
[[email protected] vhost]# cd /usr/local/nginx/conf
生成私钥key文件,还要输入私钥密码
[[email protected] conf]# openssl genrsa -des3 -out tmp.key 2048 Generating RSA private key, 2048 bit long modulus .+++ ..........................+++ e is 65537 (0x10001) Enter pass phrase for tmp.key: Verifying - Enter pass phrase for tmp.key:
转换key,取消密码,否则每次访问网页都要输入私钥密码;转换Key后,tmp.key是以后密码的,zyshan.key是没密码的,可以把tmp.key删除。
[[email protected] conf]# openssl rsa -in tmp.key -out zyshan.key Enter pass phrase for tmp.key: writing RSA key [[email protected] conf]# rm -f tmp.key
生成证书请求文件;需要填入一些信息,因为测试用可以随便填。
[[email protected] conf]# openssl req -new -key zyshan.key -out zyshan.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:11 State or Province Name (full name) []:bei^H^H^H^H^H^H Locality Name (eg, city) [Default City]:guangzhou Organization Name (eg, company) [Default Company Ltd]:guangzhou Organizational Unit Name (eg, section) []:zysyhan^H^H Common Name (eg, your name or your server's hostname) []:zyshan Email Address []:[email protected] Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:zyshan An optional company name []:zyshan
需要拿这个文件和之前生成的私钥一起生产公钥文件。
[[email protected] conf]# openssl x509 -req -days 365 -in zyshan.csr -signkey zyshan.key -out zyshan.crt Signature ok subject=/C=11/ST=bei\x08\x08\x08\x08\x08\x08/L=guangzhou/O=guangzhou/OU=zysyhan\x08\x08/CN=zyshan/[email protected] Getting Private key
这样就有三个文件了。crt公钥、csr请求文件、key私钥。
[[email protected] conf]# ls zyshan. zyshan.crt zyshan.csr zyshan.key
Nginx配置ssl
配置文件
vim /usr/local/nginx/conf/vhost/ssl.conf
配置文件内容
server { listen 443; server_name zyshan.com; index index.html index.php; root /data/wwwroot/zyshan.com; ssl on; ssl_certificate zyshan.crt; ssl_certificate_key zyshan.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; }
创建测试目录
[[email protected] vhost]# mkdir /data/wwwroot/zyshan.com
-t检查语法,unknown directive “ssl” 报错是因为之前安装nginx时的时候配置参数没有把ssl配置上去,需要到nginx目录去重新编译。
[[email protected] nginx-1.12.1]# cd /usr/local/src/nginx-1.12.1/ [[email protected] nginx-1.12.1]# ./configure --prefix=/usr/local/nginx --with-http_ssl_module [[email protected] nginx-1.12.1]# make&&make install
检查,多了一个参数:--with-http_ssl_module
[[email protected] nginx-1.12.1]# /usr/local/nginx/sbin/nginx -V nginx version: nginx/1.12.1 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC) built with OpenSSL 1.0.2k-fips 26 Jan 2017 TLS SNI support enabled configure arguments: --prefix=/usr/local/nginx --with-http_ssl_module
检查语法,重启Nginx,查看端口多了一个443端口。
[[email protected] nginx-1.12.1]# /usr/local/nginx/sbin/nginx -t nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful [[email protected] nginx-1.12.1]# /etc/init.d/nginx restart Restarting nginx (via systemctl): [ 确定 ] [[email protected] nginx-1.12.1]# netstat -lntp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4672/nginx: master tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1088/sshd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1447/master tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 4672/nginx: master tcp6 0 0 :::22 :::* LISTEN 1088/sshd tcp6 0 0 ::1:25 :::* LISTEN 1447/master tcp6 0 0 :::3306 :::* LISTEN 1405/mysqld
创建测试/data/wwwroot/zyshan.com/index.html文件
[[email protected] nginx-1.12.1]# cd /data/wwwroot/zyshan.com/ [[email protected] zyshan.com]# ls index.html index.php
把zyshan.com配置到hosts去
[[email protected] zyshan.com]# vi /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.106.150 www.qq123.com www.19.com www.zyshan.com 127.0.0.1 www.19.com zyshan.com
测试成功,只是证书是自己颁发的,浏览器认为不安全,报错而已。
[[email protected] zyshan.com]# curl https://zyshan.com curl: (60) Peer's certificate issuer has been marked as not trusted by the user. More details here: http://curl.haxx.se/docs/sslcerts.html curl performs SSL certificate verification by default, using a "bundle" of Certificate Authority (CA) public keys (CA certs). If the default bundle file isn't adequate, you can specify an alternate file using the --cacert option. If this HTTPS server uses a certificate signed by a CA represented in the bundle, the certificate verification probably failed due to a problem with the certificate (it might be expired, or the name might not match the domain name in the URL). If you'd like to turn off curl's verification of the certificate, use the -k (or --insecure) option.
php-fpm的pool
vim /usr/local/php/etc/php-fpm.conf//在[global]部分增加 include = etc/php-fpm.d/*.conf mkdir /usr/local/php/etc/php-fpm.d/ cd /usr/local/php/etc/php-fpm.d/ vim www.conf //内容如下 [www] listen = /tmp/www.sock listen.mode=666 user = php-fpm group = php-fpm pm = dynamic pm.max_children = 50 pm.start_servers = 20 pm.min_spare_servers = 5 pm.max_spare_servers = 35 pm.max_requests = 500 rlimit_files = 1024 继续编辑配置文件 vim aming.conf //内容如下 [aming] listen = /tmp/aming.sock listen.mode=666 user = php-fpm group = php-fpm pm = dynamic pm.max_children = 50 pm.start_servers = 20 pm.min_spare_servers = 5 pm.max_spare_servers = 35 pm.max_requests = 500 rlimit_files = 1024 /usr/local/php/sbin/php-fpm –t /etc/init.d/php-fpm restart
php-fpm慢执行日志
配置文件
vim /usr/local/php-fpm/etc/php-fpm.d/www.conf//加入如下内容 request_slowlog_timeout = 1 ##超过1秒的录入日志 slowlog = /usr/local/php-fpm/var/log/www-slow.log ##录入的日志路径
测试,写入一个休眠2秒的php,慢日志就会把这个慢了2秒的日志记录下来,标记出是这句休眠语句导致的慢。
配置nginx的虚拟主机test.com.conf,把unix:/tmp/php-fcgi.sock改为unix:/tmp/www.sock 重新加载nginx服务 vim /data/wwwroot/test.com/sleep.php//写入如下内容 <?php echo “test slow log”;sleep(2);echo “done”;?> curl -x127.0.0.1:80 test.com/sleep.php cat /usr/local/php-fpm/var/log/www-slow.log
php-fpm定义open_basedir
vim /usr/local/php-fpm/etc/php-fpm.d/aming.conf//加入如下内容 php_admin_value[open_basedir]=/data/wwwroot/aming.com:/tmp/ 创建测试php脚本,进行测试 再次更改aming.conf,修改路径,再次测试 配置错误日志 再次测试 查看错误日志
php-fpm进程管理
配置文件中,pm = dynamic动态进程管理;动态的时候后面的所有参数都生效。这里配置注释不用“#”而是用“;”
[[email protected] etc]# cat php-fpm.conf [global] pid = /usr/local/php-fpm/var/run/php-fpm.pid error_log = /usr/local/php-fpm/var/log/php-fpm.log [www] listen = /tmp/php-fcgi.sock ;listen = 127.0.0.1:9000 listen.mode = 666 user = php-fpm group = php-fpm pm = dynamic ;pm = static pm.max_children = 50 pm.start_servers = 20 pm.min_spare_servers = 5 pm.max_spare_servers = 35 pm.max_requests = 500 rlimit_files = 1024
测试,一开始默认启动20个子进程
[[email protected] etc]# ps aux |grep www php-fpm 1486 0.0 0.2 227244 4712 ? S 20:13 0:00 php-fpm: pool www php-fpm 1487 0.0 0.2 227244 4712 ? S 20:13 0:00 php-fpm: pool www php-fpm 1488 0.0 0.2 227244 4712 ? S 20:13 0:00 php-fpm: pool www php-fpm 1489 0.0 0.2 227244 4712 ? S 20:13 0:00 php-fpm: pool www php-fpm 1490 0.0 0.2 227244 4716 ? S 20:13 0:00 php-fpm: pool www php-fpm 1491 0.0 0.2 227244 4716 ? S 20:13 0:00 php-fpm: pool www php-fpm 1492 0.0 0.2 227244 4716 ? S 20:13 0:00 php-fpm: pool www php-fpm 1493 0.0 0.2 227244 4716 ? S 20:13 0:00 php-fpm: pool www php-fpm 1494 0.0 0.2 227244 4716 ? S 20:13 0:00 php-fpm: pool www php-fpm 1495 0.0 0.2 227244 4716 ? S 20:13 0:00 php-fpm: pool www php-fpm 1496 0.0 0.2 227244 4720 ? S 20:13 0:00 php-fpm: pool www php-fpm 1497 0.0 0.2 227244 4720 ? S 20:13 0:00 php-fpm: pool www php-fpm 1498 0.0 0.2 227244 4720 ? S 20:13 0:00 php-fpm: pool www php-fpm 1499 0.0 0.2 227244 4720 ? S 20:13 0:00 php-fpm: pool www php-fpm 1500 0.0 0.2 227244 4720 ? S 20:13 0:00 php-fpm: pool www php-fpm 1501 0.0 0.2 227244 4720 ? S 20:13 0:00 php-fpm: pool www php-fpm 1502 0.0 0.2 227244 4720 ? S 20:13 0:00 php-fpm: pool www php-fpm 1504 0.0 0.2 227244 4720 ? S 20:13 0:00 php-fpm: pool www php-fpm 1505 0.0 0.2 227244 4720 ? S 20:13 0:00 php-fpm: pool www php-fpm 1506 0.0 0.2 227244 4720 ? S 20:13 0:00 php-fpm: pool www root 5029 0.0 0.0 112720 972 pts/0 R+ 22:50 0:00 grep --color=auto www
配置pm = static静态,只有后面跟着的那一行生效,一开始就运行50个子进程,后面的参数都不生效了。
pm = static pm.max_children = 50
检查语法,重启服务,测试,确实是默认启动50个子进程
[[email protected] etc]# /usr/local/php-fpm/sbin/php-fpm -t [08-Jul-2018 22:57:13] NOTICE: configuration file /usr/local/php-fpm/etc/php-fpm.conf test is successful [[email protected] etc]# /etc/init.d/php-fpm restart Gracefully shutting down php-fpm . done Starting php-fpm done [[email protected] etc]# ps aux |grep www php-fpm 5088 0.0 0.2 227244 4716 ? S 22:57 0:00 php-fpm: pool www php-fpm 5089 0.0 0.2 227244 4716 ? S 22:57 0:00 php-fpm: pool www php-fpm 5090 0.0 0.2 227244 4720 ? S 22:57 0:00 php-fpm: pool www php-fpm 5091 0.0 0.2 227244 4720 ? S 22:57 0:00 php-fpm: pool www php-fpm 5092 0.0 0.2 227244 4724 ? S 22:57 0:00 php-fpm: pool www php-fpm 5093 0.0 0.2 227244 4724 ? S 22:57 0:00 php-fpm: pool www php-fpm 5094 0.0 0.2 227244 4724 ? S 22:57 0:00 php-fpm: pool www php-fpm 5095 0.0 0.2 227244 4724 ? S 22:57 0:00 php-fpm: pool www php-fpm 5096 0.0 0.2 227244 4724 ? S 22:57 0:00 php-fpm: pool www php-fpm 5097 0.0 0.2 227244 4724 ? S 22:57 0:00 php-fpm: pool www php-fpm 5098 0.0 0.2 227244 4724 ? S 22:57 0:00 php-fpm: pool www php-fpm 5099 0.0 0.2 227244 4724 ? S 22:57 0:00 php-fpm: pool www php-fpm 5100 0.0 0.2 227244 4724 ? S 22:57 0:00 php-fpm: pool www php-fpm 5101 0.0 0.2 227244 4724 ? S 22:57 0:00 php-fpm: pool www php-fpm 5102 0.0 0.2 227244 4724 ? S 22:57 0:00 php-fpm: pool www php-fpm 5103 0.0 0.2 227244 4724 ? S 22:57 0:00 php-fpm: pool www php-fpm 5104 0.0 0.2 227244 4724 ? S 22:57 0:00 php-fpm: pool www php-fpm 5105 0.0 0.2 227244 4724 ? S 22:57 0:00 php-fpm: pool www php-fpm 5106 0.0 0.2 227244 4728 ? S 22:57 0:00 php-fpm: pool www php-fpm 5107 0.0 0.2 227244 4728 ? S 22:57 0:00 php-fpm: pool www php-fpm 5108 0.0 0.2 227244 4728 ? S 22:57 0:00 php-fpm: pool www php-fpm 5109 0.0 0.2 227244 4728 ? S 22:57 0:00 php-fpm: pool www php-fpm 5110 0.0 0.2 227244 4728 ? S 22:57 0:00 php-fpm: pool www php-fpm 5111 0.0 0.2 227244 4728 ? S 22:57 0:00 php-fpm: pool www php-fpm 5112 0.0 0.2 227244 4728 ? S 22:57 0:00 php-fpm: pool www php-fpm 5113 0.0 0.2 227244 4728 ? S 22:57 0:00 php-fpm: pool www php-fpm 5114 0.0 0.2 227244 4728 ? S 22:57 0:00 php-fpm: pool www php-fpm 5115 0.0 0.2 227244 4728 ? S 22:57 0:00 php-fpm: pool www php-fpm 5116 0.0 0.2 227244 4728 ? S 22:57 0:00 php-fpm: pool www php-fpm 5117 0.0 0.2 227244 4728 ? S 22:57 0:00 php-fpm: pool www php-fpm 5118 0.0 0.2 227244 4728 ? S 22:57 0:00 php-fpm: pool www php-fpm 5119 0.0 0.2 227244 4728 ? S 22:57 0:00 php-fpm: pool www php-fpm 5120 0.0 0.2 227244 4728 ? S 22:57 0:00 php-fpm: pool www php-fpm 5121 0.0 0.2 227244 4728 ? S 22:57 0:00 php-fpm: pool www php-fpm 5122 0.0 0.2 227244 4732 ? S 22:57 0:00 php-fpm: pool www php-fpm 5123 0.0 0.2 227244 4732 ? S 22:57 0:00 php-fpm: pool www php-fpm 5124 0.0 0.2 227244 4732 ? S 22:57 0:00 php-fpm: pool www php-fpm 5125 0.0 0.2 227244 4732 ? S 22:57 0:00 php-fpm: pool www php-fpm 5126 0.0 0.2 227244 4732 ? S 22:57 0:00 php-fpm: pool www php-fpm 5127 0.0 0.2 227244 4732 ? S 22:57 0:00 php-fpm: pool www php-fpm 5128 0.0 0.2 227244 4732 ? S 22:57 0:00 php-fpm: pool www php-fpm 5129 0.0 0.2 227244 4732 ? S 22:57 0:00 php-fpm: pool www php-fpm 5130 0.0 0.2 227244 4732 ? S 22:57 0:00 php-fpm: pool www php-fpm 5131 0.0 0.2 227244 4732 ? S 22:57 0:00 php-fpm: pool www php-fpm 5132 0.0 0.2 227244 4732 ? S 22:57 0:00 php-fpm: pool www php-fpm 5133 0.0 0.2 227244 4732 ? S 22:57 0:00 php-fpm: pool www php-fpm 5134 0.0 0.2 227244 4732 ? S 22:57 0:00 php-fpm: pool www php-fpm 5135 0.0 0.2 227244 4732 ? S 22:57 0:00 php-fpm: pool www php-fpm 5136 0.0 0.2 227244 4732 ? S 22:57 0:00 php-fpm: pool www php-fpm 5137 0.0 0.2 227244 4732 ? S 22:57 0:00 php-fpm: pool www
pm.max_children = 50 //最大子进程数,ps aux可以查看pm.start_servers = 20 //启动服务时会启动的进程数pm.min_spare_servers = 5 //定义在空闲时段,子进程数的最少数量,如果达到这个数值时,php-fpm服务会自动派生新的子进程。pm.max_spare_servers = 35 //定义在空闲时段,子进程数的最大值,如果高于这个数值就开始清理空闲的子进程。pm.max_requests = 500 //定义一个子进程最多处理的请求数,也就是说在一个php-fpm的子进程最多可以处理这么多请求,当达到这个数值时,它会自动退出
拓展:
针对请求的uri来代理 http://ask.apelearn.com/question/1049 根据访问的目录来区分后端的web http://ask.apelearn.com/question/920 nginx长连接 http://www.apelearn.com/bbs/thread-6545-1-1.html nginx算法分析 http://blog.sina.com.cn/s/blog_72995dcc01016msi.html nginx中的root和alias区别 http://blog.****.net/21aspnet/article/details/6583335 nginx的alias和root配置 http://www.ttlsa.com/nginx/nginx-root_alias-file-path-configuration/ http://www.iigrowing.cn/shi-yan-que-ren-nginx-root-alias-location-zhi-ling-shi-yong-fang-fa.html 这个更详细
直播拓展:
证书 https://coding.net/u/aminglinux/p/nginx/git/blob/master/ssl/ca.md Nginx几种负载均衡算法及配置实例 https://blog.whsir.com/post-1482.html Nginx正向代理配置 https://coding.net/u/aminglinux/p/nginx/git/blob/master/proxy/z_proxy.md