LNMP架构 (6) 之 php-fpm的pool、慢执行日志、open_basedir、进程管理

1. php-fpm的pool

为了避免因多站点使用同一个pool时,因为一个站点故障导致pool出问题,进而影响使用同一个pool的其他站点的正常运行,我们有必要对每一个站点设置一个单独的pool。

1.1 为php-fpm配置多个pool

编辑php-fpm配置文件:

[root@host etc]# vim /usr/local/php-fpm/etc/php-fpm.conf  

[www]
listen = /tmp/php-fcgi.sock
#listen = 127.0.0.1:9000
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
……
[zhouqun.com]      //添加新的pool
listen = /tmp/zhouqun.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

1.2 语法检测

[root@host etc]# /usr/local/php-fpm/sbin/php-fpm -t
[12-Sep-2017 23:26:57] NOTICE: configuration file /usr/local/php-fpm/etc/php-fpm.conf test is successful

1.3 重新加载配置文件

[root@host etc]# /etc/init.d/php-fpm reload
Reload service php-fpm  done

1.4 查看进程

[root@host etc]# ps aux |grep php-fpm

php-fpm  6222  0.0  0.4 226640  4716 ?        S    16:10  0:00 php-fpm: pool www
php-fpm  6223  0.0  0.4 226640  4712 ?        S    16:10  0:00 php-fpm: pool zhouqun.com

1.5 为站点设置pool

[root@host vhost]# vim /usr/local/nginx/conf/vhost/aaa.com.conf

location ~ .php$
    {
        include fastcgi_params;
        fastcgi_pass unix:/tmp/zhouqun.sock;    //把fastcgi_pass地址改为和php-fpm.conf中一样的地址就可以
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /data/wwwroot/default$fastcgi_script_name;
    }

1.6 添加php-fpm.conf子配置文件

为了便于管理,可以将php-fpm中的每个pool单独进行管理。进行如下操作,添加php-fpm子配置文件:

[root@host vhost]# vim /usr/local/php-fpm/etc/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
include = etc/php-fpm.d/*.conf   //添加
#在全局变量版块添加参数“include = etc/php-fpm.d/*.conf”。然后可以清除php-fpm配置文件中其他参数,再到php-fpm.d目录下进行单独设置。

1.7 创建指定目录

[root@host vhost]# cd /usr/local/php-fpm/etc/
[root@host etc]# mkdir php-fpm.d

[root@host etc]# cd php-fpm.d/

1.8 创建php-fpm子配置文件

[root@host php-fpm.d]# vim www.conf
[www]
listen = /tmp/php-fcgi.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

[root@host php-fpm.d]# vim zhouqun.conf
[zhouqun.com]
listen = /tmp/zhouqun.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

1.9 检查语法错误并重启:

[root@host php-fpm.d]# /usr/local/php-fpm/sbin/php-fpm -t
[16-Aug-2017 16:49:17] NOTICE: configuration file /usr/local/php-fpm/etc/php-fpm.conf test is successful

[root@host php-fpm.d]# /etc/init.d/php-fpm reload
Reload service php-fpm  done

查看php-fpm进程信息还是使用ps命令。

2. php-fpm慢执行日志

php网站莫名的访问很慢,可以通过慢执行日志找到症结所在,所以满日志非常重要,php网站强烈推荐使用LNMP架构搭建。

2.1 开启慢执行日志:

[root@host php-fpm.d]# 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           //日志存放地址
检测并重加载
[root@host php-fpm.d]# /usr/local/php-fpm/sbin/php-fpm -t
[root@host php-fpm.d]# /etc/init.d/php-fpm reload

2.2 试验

在使用www pool的站点添加文件:

[root@host php-fpm.d]# vim /data/wwwroot/test.com/sleep.php   //创建一个.php文件,故意让它休眠2秒,让它运行缓慢
<?php
echo "test slow log";
sleep(2);     
echo "done";
?>

2.3 检测

[root@host php-fpm.d]# curl -x127.0.0.1:80 test.com/sleep.php 
test slow log done

2.4 查看慢日志

[root@host php-fpm.d]# tail /usr/local/php-fpm/var/log/www-slow.log 

[12-Sep-2017 23:42:23]  [pool www] pid 4236
script_filename = /data/wwwroot/test.com/sleep.php
[0x00007fe027r0e2f5] sleep() /data/wwwroot/test.com/sleep.php:3      //显示文件的第三行导致的访问慢,因为第三行就是sleep命令

3. php-fpm定义open_basedir

在php-fpm服务中,当一台服务器跑多个网站时,用open_basedir限定各个站点所能访问的服务器上的目录的范围,可以针对每个pool设定open _ basedir。

3.1 核心配置参数:

[root@host ~]# vim /usr/local/php-fpm/etc/php-fpm.d/www.conf  
……
php_admin_value[open_basedir]=/data/wwwroot/test.com:/tmp/     //修改

3.2 创建测试PHP脚本

[root@host php-fpm.d]# vim /data/wwwroot/test.com/1.php
<?php
echo "This is a test php of open_basedir";

3.3 测试

[root@host php-fpm.d]# curl -x127.0.0.1:80 test.com/1.php
This is a test php of open_basedir

4. php-fpm进程管理

php-fpm中pool配置参数解析:

[root@host php-fpm.d]# vim www.conf
[www]
listen = /tmp/php-fcgi.sock
listen.mode = 666
user = php-fpm
group = php-fpm
pm = dynamic
#设置进程启动方式(dynamic表示动态,static表示静态)
#只有此处设置为dynamic,下面的配置才生效
pm.max_children = 50   //最多可启动的子进程数量
pm.start_servers = 20    //设定初始启动的进程数量
pm.min_spare_servers = 5      //表示php-fpm空闲时最少要有几个子进程
pm.max_spare_servers = 35   //表示php-fpm空闲时最多要有几个子进程
pm.max_requests = 500          //表示一个子进程最多可接受多少个请求
rlimit_files = 1024                     //表示每个子进程打开的多少个文件句柄
request_slowlog_timeout = 1    //当请求超过1秒开始记录日志
slowlog = /usr/local/php-fpm/var/log/www-slow.log      //日志存放地址
php_admin_value[open_basedir]=/data/wwwroot/test.com:/tmp/

LNMP架构 (5) 之 Nginx负载均衡、ssl原理、生成ssl密钥对、配置ssl

1. Nginx负载均衡

Nginx负载均衡就是指 当代理服务器将自定义的域名解析到多个指定IP时,通过upstream模块来保证用户可以通过代理服务器正常访问各个IP(反向代理多台服务器就是负载均衡)。

1.1 负载均衡配置参数

[root@host ~]# vim /usr/local/nginx/conf/vhost/load.conf
upstream qq
#自定义域名
{
    ip_hash;
#目的是为了保证同一个用户始终保持在同一台机器上
#还有就是为了当域名指向多个IP时,保证每个用户始终解析到同一IP
    server 61.135.157.156:80;
    server 125.39.240.113:80;
#指定web服务器的IP
}
server
{
    listen 80;
    server_name www.qq.com;
    location /
    {
        proxy_pass      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;
    }
}

1.2 检测

代理前

[root@host ~]# curl -x127.0.0.1:80 www.qq.com 
This is the default directory.

#没使用代理时,会直接解析到默认的虚拟主机。

代理后

[root@host ~]# /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
[root@host ~]# /usr/local/nginx/sbin/nginx -s reload
[root@host ~]# curl -x127.0.0.1:80 www.qq.com
……
#使用代理后,会解析到代理服务器所指向的IP的网页代码

1.3 dig命令

dig命令是常用域名的解析工具,可以寻找域名的全部IP。

如果服务器中没有安装命令

[root@host ~]# yum install -y bind-utils

解析qq网站的全部IP

[root@host ~]# dig www.qq.com

;; ANSWER SECTION:
www.qq.com.        138    IN    A    61.135.157.156
www.qq.com.        138    IN    A    125.39.240.113

;; Query time: 12 msec
;; SERVER: 119.29.29.29#53(119.29.29.29)
;; WHEN: 二 9月 12 22:44:23 CST 2017
;; MSG SIZE  rcvd: 61

2. ssl原理

SSL(Secure Sockets Layer 安//全//套接层)协议,及其继任者TLS(Transport Layer Security传输层安全)协议,是为网络通信提供安全及数据完整性的一种安全协议。

2.1 http、https、tcp

  • HTTP超文本传输协议(HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。
  • HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),简单讲是HTTP的安全加密版。
  • HTTP默认的端口号为80,HTTPS的端口号为443。
  • TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。默认监听80端口。
  • http是应用层协议, tcp是传输层。 http使用tcp传输文本数据; http只是定义了tcp数据的解析方式

2.2 SSL工作流程

  • 浏览器发送一个https的请求给服务器;
  • 服务器要有一套数字证书,可以自己制作(后面的操作就是阿铭自己制作的证书),也可以向组织申请,区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出>提示页面,这套证书其实就是一对公钥和私钥;
  • 服务器会把公钥传输给客户端;
  • 客户端(浏览器)收到公钥后,会验证其是否合法有效,无效会有警告提醒,有效则会生成一串随机数,并用收到的公钥加密;
  • 客户端把加密后的随机字符串传输给服务器;
  • 服务器收到加密随机字符串后,先用私钥解密(公钥加密,私钥解密),获取到这一串随机数后,再用这串随机字符串加密传输的数据(该加密为对称加密,所谓对称加密,就是将数据和私钥也就是这个随机字符串>通过某种算法混合在一起,这样除非知道私钥,否则无法获取数据内容);
  • 服务器把加密后的数据传输给客户端;
  • 客户端收到数据后,再用自己的私钥也就是那个随机字符串解密;

3. 生成ssl密钥对

SSL证书就是一对公钥和私钥。

3.1 准备工具

如果虚拟机中没有此工具,手动安装:

[root@host ~]# yum install -y openssl

3.2 创建私钥

[root@host ~]# cd /usr/local/nginx/conf/

[root@host conf]# openssl genrsa -des3 -out tmp.key 2048  //生成SSL密钥
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,取消密码

[root@host conf]# openssl rsa -in tmp.key -out host.key  //转换一下key,将tmp.key 转换为没密码的host.key

Enter pass phrase for tmp.key:
writing RSA key

[root@host conf]# rm -f tmp.key  //删除tmp.key

3.3 自己生成证书

[root@host conf]# openssl req -new -key host.key -out host.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) []:BeiJing
Locality Name (eg, city) [Default City]:BeiJing
Organization Name (eg, company) [Default Company Ltd]:BeiJing
Organizational Unit Name (eg, section) []:BeiJing
Common Name (eg, your name or your server's hostname) []:host
Email Address []:[email protected]
#以上是配置证书信息,因为是自己颁发给自己的证书,就随意瞎填或者干脆Enter跳过,如果是正式应用在自己的网站上,最好规范填写。

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:123456
An optional company name []:123456

3.4 创建公钥

[root@host conf]# openssl x509 -req -days 365 -in host.csr -signkey host.key -out host.crt  //这里的aminglinux.crt为公钥

Signature ok
subject=/C=11/ST=BeiJing/L=BeiJing/O=BeiJing/OU=BeiJing/CN=host/[email protected]
Getting Private key

4. Nginx配置ssl

4.1 配置文件

[root@host conf]# cd vhost/

[root@host vhost]# vim ssl.conf
server
{
    listen 443;
    server_name zhouqun.com;
    index index.html index.php;
    root /data/wwwroot/zhouquncom;
    ssl on;      //开启ssl
    ssl_certificate host.crt;     //配置公钥
    ssl_certificate_key host.key;        //配置私钥
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;      ///配置协议
}

[root@host vhost]# mkdir /data/wwwroot/zhouqun.com

4.2 检测

[root@host conf]# /usr/local/nginx/sbin/nginx -t
nginx: [emerg] unknown directive "ssl" in /usr/local/nginx/conf/vhost/ssl.conf:7       //报错了
nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed

4.3 报错 unknown directive “ssl” 未识别ssl配置,需要重新编译nginx,加上–with-http_ssl_module

[root@host conf]# cd /usr/local/src/nginx-1.12.1/

[root@host nginx-1.12.1]# ./configure --prefix=/usr/local/nginx --with-http_ssl_module  

[root@host conf]# make
[root@host conf]# make install

[root@host 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

[root@host nginx-1.12.1]# /etc/init.d/nginx restart
Restarting nginx (via systemctl):                          [  OK  ]

[root@host 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      5991/nginx: master  
tcp        0      0 0.0.0.0:22              0.0.0.0:*              LISTEN      1735/sshd          
tcp        0      0 127.0.0.1:25            0.0.0.0:*              LISTEN      2040/master        
tcp        0      0 0.0.0.0:443            0.0.0.0:*              LISTEN      5991/nginx: master  
tcp6      0      0 :::3306                :::*                    LISTEN      1990/mysqld        
tcp6      0      0 :::22                  :::*                    LISTEN      1735/sshd          
tcp6      0      0 ::1:25                  :::*                    LISTEN      2040/master  

nginx监听80和443端口。

4.4 测试

[root@host nginx-1.12.1]# cd /data/wwwroot/zhouqun.com/

[root@host adai.com]# vim index.html

This is ssl.

4.5 添加本地域名:

[root@host adai.com]# vim /etc/hosts
127.0.0.1  zhouqun.com

[root@host vhost]# curl https://zhouqun.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.

因为该证书是自己创建的,没有符合https组织的规范,不能被正确识别,如果换上正规的证书,就没问题了。

所以,如果要使用浏览器检测,那么进行该测试之前,需要更改Windows的hosts文件,不然就会证书出错的。

LNMP架构 (4) 之 Nginx的防盗链、访问控制、解析php相关配置

1. Nginx防盗链

Nginx防盗链可结合日志管理一起配置,因为该配置也要使用location板块

[root@host ~]# vim /usr/local/nginx/conf/vhost/test.com.conf
……
location ~* ^.+.(gif|jpg|png|swf|flv|rar|zip|doc|pdf|gz|bz2|jpeg|bmp|xls)$
{
    expires 7d;
    valid_referers none blocked server_names  *.test.com ;
    #定义referer白名单
    if ($invalid_referer) {
        return 403;
    #if函数的意思是:如果不是白名单内的域名,返回值:403
    }
    access_log off;
}
……

[root@host ~]# /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
[root@host ~]# /usr/local/nginx/sbin/nginx -s reload

检查
[root@host ~]# curl -e "http://www.baidu.com/1.txt" -x127.0.0.1:80 -I test.com/baidu.png
HTTP/1.1 403 Forbidden
Server: nginx/1.12.1
Date: Mon, 11 Sep 2017 11:25:47 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
访问被拒绝,防盗链生效

2. Nginx访问控制

只允许几个指定IP通过访问/admin/目录的请求

[root@host ~]# vim /usr/local/nginx/conf/vhost/test.com.conf 
……
location /admin/
    {
#设置IP白名单
    allow 192.168.8.132;
    allow 127.0.0.1;
    deny all;

    }


[root@host ~]# /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
[root@host ~]# /usr/local/nginx/sbin/nginx -s reload

创建目录

[root@host ~]# mkdir /data/wwwroot/test.com/admin
[root@host ~]#  echo “test,test”>/data/wwwroot/test.com/admin/1.html

测试

[root@host ~]# curl -x127.0.0.1:80  test.com/admin/1.html
“test,test”
[root@host ~]# curl -x192.168.2.107:80  test.com/admin/1.html
“test,test”

访问控制

#正则匹配
location ~ .*(abc|image)/.*.php$
{
        deny all;
}


#user_agent限制
if ($http_user_agent ~ 'Spider/3.0|YoudaoBot|Tomato')
{
      return 403;
}

#deny all和return 403效果一样

#12.15 Nginx解析php相关配置 核心配置文件

[root@host ~]# vim /usr/local/nginx/conf/vhost/test.com.conf
……
location ~ .php$
    {
        include fastcgi_params;
#fastcgi_pass 127.0.0.1:9000
        fastcgi_pass unix:/tmp/php-fcgi.sock;
#fastcgi_pass 有两种监听格式,要保证Nginx和php-fpm中格式是一致的,否则会报502错误
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /data/wwwroot/test.com$fastcgi_script_name;
#fastcgi _param SCRIPT _FILENAME所在行的路径要和root路径一致
    }

3. Nginx代理

在计算机网络中,反向代理是代理服务器的一种。它根据客户端的请求,从后端的服务器上获取资源,然后再将这些资源返回给客户端。与前向代理不同,前向代理作为一个媒介将互联网上获取的资源返回给相关联的客户端,而反向代理是在服务器端作为代理使用,而不是客户端。

3.1 Nginx作为反向代理的特点

  • 接收用户请求是异步的,即先将用户请求全部接收下来,再一次性发送后后端web服务器,极大的减轻后端web服务器的压力;

  • nginx代理和后端web服务器间无需长连接;
    发送响应报文时,是边接收来自后端web服务器的数据,边发送给客户端的;

  • 调度灵活。NGINX工作在网络协议栈的第七层,能够对HTTP应用请求进行解析和分流,支持比较复杂的正则规则,具有更优化的负载均衡效果。

  • 网络依赖型低。NGINX对网络的依赖程度非常低,理论上讲,只要能够ping通就可以实施负载均衡,而且可以有效区分内网和外网流量。

  • 支持服务器检测。NGINX能够根据应用服务器处理页面返回的状态码、超时信息等检测服务器是否出现故障,并及时返回错误的请求重新提交到其它节点上。

3.2 工作原理

Nginx代理是在一台代理服务器中自定义一个域名,该域名指向一个IP,然后将用户的请求通过这台代理服务器访问指定的IP所对应的web服务器。

3.3 进入虚拟主机目录

[root@host ~]# cd /usr/local/nginx/conf/vhost/

3.4 创建代理服务器

[root@host vhost]# vim proxy.conf
server
{
    listen 80;
    server_name ask.apelearn.com;
#定义域名
    location /
    {
        proxy_pass      http://121.201.9.155/;
#指定被代理(被访问)的IP(web服务器IP)
        proxy_set_header Host  $host;
#$host指的是代理服务器的servername(也是被代理IP的域名)
        proxy_set_header X-Real-IP      $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
设置好以后,就可以访问aminglinux论坛了

3.5 检测验证

#之前
[root@host vhost]# curl -x127.0.0.1:80 ask.apelearn.com/robots.txt
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.12.1</center>
</body>
</html>

#之后
[root@host vhost]# /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
[root@host vhost]# /usr/local/nginx/sbin/nginx -s reload


[root@host vhost]# curl -x127.0.0.1:80 ask.apelearn.com/robots.txt
#
# robots.txt for MiWen
#

User-agent: *

Disallow: /?/admin/
Disallow: /?/people/
Disallow: /?/question/
Disallow: /account/
Disallow: /app/
Disallow: /cache/

LNMP架构 (3) 之 Nginx访问日志、日志切割、静态文件不记录日志和过期时间

1. Nginx访问日志

1.1 日志格式

[root@host ~]# vim /usr/local/nginx/conf/nginx.conf   //搜索log_format
... ...
log_format combined_realip '$remote_addr $http_x_forwarded_for [$time_local]'
    ' $host "$request_uri" $status'
    ' "$http_referer" "$http_user_agent"';
#combined_realip是日志名称 
# 后面带引号和$的是日志内容

1.2 日志格式参数注释

未分类

1.3 定义虚拟主机日志格式(一定要先定义nginx.conf中的日志格式,才能在这里调用和再定义)

[root@host ~]# cd /usr/local/nginx/conf/vhost/
[root@host vhost]# ls
aaa.com.conf  test.com.conf

[root@host vhost]# vim aaa.com.conf     //定义aaa.com.conf日志格式 
……
access_log /tmp/aaa.com.log combined_realip;
#指定日志位置和格式

检查错误:
[root@host vhost]# /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

1.4 检查

[root@host vhost]# curl -x127.0.0.1:80 aaacom 
This is aaa.com
[root@host vhost]# cat /tmp/aaa.com.log 
127.0.0.1 - [8/Sep/2017:22:39:68 +0800] aaa.com "/" 200 "-" "curl/7.29.0"

2. Nginx日志切割

因为Nginx没有自带的日志切割工具,所以需要借助系统日志切割命令或自己编写日志切割脚本。

2.1 日志切割脚本

以后把所有的shell脚本统一保存位置:/usr/local/sbin/

[root@host vhost]# vim /usr/local/sbin/nginx_log_rotate.sh

#! /bin/bash
d=`date -d "-1 day" +%Y%m%d` 
#定义切割时间(切割一天前的日志)
logdir="/tmp/"
#此处指定要切割的日志路径(该路径来自虚拟主机配置文件)
nginx_pid="/usr/local/nginx/logs/nginx.pid"
#调用pid的目的是为了执行命令:/bin/kill -HUP `cat $nginx_pid`
#该命令相当于命令:nginx -s reload(重新加载文件),确保与虚拟主机配置文件变更保持同步
#该地址来自nginx配置文件
cd $logdir
for log in `ls *.log`
do
    mv $log $log-$d
done
#这里使用通配进行循环,对所有符合条件的日志文件进行切割
/bin/kill -HUP `cat $nginx_pid`
#执行此命令进行重新加载生成新的日志文件来记录新的日志

2.2 执行该脚本

[root@host vhost]# sh -x /usr/local/sbin/nginx_log_rotate.sh
++ date -d '-1 day' +%Y%m%d
+ d=20170909
+ logdir=/tmp/
+ nginx_pid=/usr/local/nginx/logs/nginx.pid
+ cd /tmp/
++ ls test.com.log yum.log
+ for log in '`ls *.log`'
+ mv test.com.log test.com.log-20170909
+ for log in '`ls *.log`'
+ mv yum.log yum.log-20170909
++ cat /usr/local/nginx/logs/nginx.pid
+ /bin/kill -HUP 59154

2.3添加到系统任务计划

[root@host vhost]# vim /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed

0 3 * * * /bin/bash /usr/local/sbin/nginx_log_rotate.sh
#每天凌晨3点切割一次前一天日志

[root@host vhost]# chmod +x /usr/local/sbin/nginx_log_rotate.sh  //加上可执行权限

3. 静态文件不记录日志和过期时间

3.1 核心配置参数

[root@host vhost]# vim test.com.conf
location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
    #匹配文件类型
    {
          expires      7d;
          #过期时间为7天
          access_log off;
          #不记录该类型文件的访问日志
    }
location ~ .*.(js|css)$
    {
          expires      12h;
          #过期时间为12小时
          access_log off;
          #不记录该类型文件的访问日志
    }
    access_log /tmp/test.com.log combined_realip;
    #指定日志位置及格式

3.2 检测

[root@host vhost]# /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
[root@host vhost]# /usr/local/nginx/sbin/nginx -s reload

访问index.html文件
[root@host vhost]# !curl
curl -x127.0.0.1:80 test.com
This is test.com

[root@host vhost]# !cat
cat /tmp/test.com.log 
127.0.0.1 - [9/Sep/2017:00:12:26 +0800] test.com "/" 200 "-" "curl/7.29.0"
#有日志

访问baidu.png文件
[root@host test.com]# curl -x127.0.0.1:80 test.com/baidu.png -I
HTTP/1.1 200 OK
Server: nginx/1.12.1
Date: Sat, 9 Aug 2017 09:47:57 GMT
Content-Type: image/png
Content-Length: 3706
Last-Modified: Sat, 09 Sep 2017 01:13:35 GMT
Connection: keep-alive
ETag: "59805459-e7a"
Expires: Sat, 09 Sep 2017 00:47:46 GMT
Cache-Control: max-age=604800
Accept-Ranges: bytes
#max-age=604800s=7天,即该文件缓存的过期时间为7天!

[root@host test.com]# cat /tmp/test.com.log 
127.0.0.1 - [9/Sep/2017:00:13:39+0800] test.com "/" 200 "-" "curl/7.29.0"
#无该文件的访问日志!!!

LNMP架构 (2)之 Nginx安装、默认虚拟主机、用户认证、域名重定向、配置文件详解

5. Nginx安装

5.1 准备

[root@host ~]# cd /usr/local/src/

[root@host src]# wget http://nginx.org/download/nginx-1.12.1.tar.gz

[root@host src]# tar zxvf nginx-1.12.1.tar.gz 

5.2 安装

[root@host src]# cd nginx-1.12.1/

[root@host nginx-1.12.1]# ./configure --prefix=/usr/local/nginx   //如果需要支持某模块,可以在此添加,如HTTPS、SSL等,我们这里就先不安装,后面再编译进去

[root@host nginx-1.12.1]# make && make install  //编译
[root@host nginx-1.12.1]# echo $?           //检查
0
[root@host nginx-1.12.1]# cd /usr/local/nginx/
[root@host nginx]# ls
conf  html  logs  sbin

5.3 配置

添加nginx到启动服务

[root@host nginx]# vim /etc/init.d/nginx   //创建启动脚本,写入以下代码

#!/bin/bash
# chkconfig: - 30 21
# description: http service.
# Source Function Library
. /etc/init.d/functions
# Nginx Settings
NGINX_SBIN="/usr/local/nginx/sbin/nginx"
NGINX_CONF="/usr/local/nginx/conf/nginx.conf"
NGINX_PID="/usr/local/nginx/logs/nginx.pid"
RETVAL=0
prog="Nginx"
start() 
{
    echo -n $"Starting $prog: "
    mkdir -p /dev/shm/nginx_temp
    daemon $NGINX_SBIN -c $NGINX_CONF
    RETVAL=$?
    echo
    return $RETVAL
}
stop() 
{
    echo -n $"Stopping $prog: "
    killproc -p $NGINX_PID $NGINX_SBIN -TERM
    rm -rf /dev/shm/nginx_temp
    RETVAL=$?
    echo
    return $RETVAL
}
reload()
{
    echo -n $"Reloading $prog: "
    killproc -p $NGINX_PID $NGINX_SBIN -HUP
    RETVAL=$?
    echo
    return $RETVAL
}
restart()
{
    stop
    start
}
configtest()
{
    $NGINX_SBIN -c $NGINX_CONF -t
    return 0
}
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  reload)
        reload
        ;;
  restart)
        restart
        ;;
  configtest)
        configtest
        ;;
  *)
        echo $"Usage: $0 {start|stop|reload|restart|configtest}"
        RETVAL=1
esac
exit $RETVAL


检查语法
[root@host nginx]# /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

更改权限
[root@host nginx]# chmod 755 /etc/init.d/nginx

添加到系统服务
[root@host nginx]# chkconfig --add nginx
[root@host nginx]# chkconfig nginx on

更改Nginx的配置文件

[root@host nginx]# cd /usr/local/nginx/conf/    
[root@host conf]# mv nginx.conf nginx.conf.bak  //把Nginx自带脚本存做备份,创建自己的脚本

[root@host conf]# vim nginx.conf    //写入以下内容

user nobody nobody;
#定义启动Nginx服务的用户
worker_processes 2;
#定义子进程数
error_log /usr/local/nginx/logs/nginx_error.log crit;
pid /usr/local/nginx/logs/nginx.pid;
worker_rlimit_nofile 51200;
#指定Nginx最多可打开的文件数
events
{
    use epoll;
    worker_connections 6000;
#进程最大连接数
}

http
{
    include mime.types;
    default_type application/octet-stream;
    server_names_hash_bucket_size 3526;
    server_names_hash_max_size 4096;
    log_format combined_realip '$remote_addr $http_x_forwarded_for [$time_local]'
    ' $host "$request_uri" $status'
    ' "$http_referer" "$http_user_agent"';
    sendfile on;
    tcp_nopush on;
    keepalive_timeout 30;
    client_header_timeout 3m;
    client_body_timeout 3m;
    send_timeout 3m;
    connection_pool_size 256;
    client_header_buffer_size 1k;
    large_client_header_buffers 8 4k;
    request_pool_size 4k;
    output_buffers 4 32k;
    postpone_output 1460;
    client_max_body_size 10m;
    client_body_buffer_size 256k;
    client_body_temp_path /usr/local/nginx/client_body_temp;
    proxy_temp_path /usr/local/nginx/proxy_temp;
    fastcgi_temp_path /usr/local/nginx/fastcgi_temp;
    fastcgi_intercept_errors on;
    tcp_nodelay on;
    gzip on;
    gzip_min_length 1k;
    gzip_buffers 4 8k;
    gzip_comp_level 5;
    gzip_http_version 1.1;
    gzip_types text/plain application/x-javascript text/css text/htm 
    application/xml;
    server
    {
        listen 80;
        server_name localhost;
        index index.html index.htm index.php;
        root /usr/local/nginx/html;
        location ~ .php$
#虚拟主机配置
        {
            include fastcgi_params;
            fastcgi_pass unix:/tmp/php-fcgi.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME /usr/local/nginx/html$fastcgi_script_name;
#PHP解析配置
        }    
    }
}

检测语法:
[root@host conf]# /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

启动Nginx服务:
[root@host conf]# /etc/init.d/nginx start
Starting nginx (via systemctl):                            [  确定  ]

查看链接情况
[root@host conf]# ps aux|grep nginx   
root    17603  0.0  0.0  20500  624 ?        Ss  22:57  0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
nobody  17604  0.0  0.1  22944  3212 ?        S    22:57  0:00 nginx: worker process
nobody  17605  0.0  0.1  22944  3212 ?        S    22:57  0:00 nginx: worker process
root    17607  0.0  0.0 112680  972 pts/1    R+  22:57  0:00 grep --color=auto nginx

[root@host conf]# ps aux|grep php-fpm
root    17609  0.0  0.0 112680  968 pts/1    R+  22:58  0:00 grep --color=auto php-fpm

5.4 检查

[root@host conf]# curl localhost    //curl测试,结果如下,表示正常

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

检测PHP解析

[root@host conf]# vim /usr/local/nginx/html/1.php
<?php
echo "test php scripts.";
?>

[root@host conf]# curl localhost/1.php
test php scripts.

6. 默认虚拟主机

6.1 编辑Nginx配置文件,删除原有server内容,添加如下内容:

[root@host ~]# cd /usr/local/nginx/conf
[root@host conf]# vim /usr/local/nginx/conf/nginx.conf
……
include vhost/*.conf;      //创建一个虚拟主机配置文件子目录(相当于增加子虚拟主机)

[root@host conf]# mkdir vhost      //创建配置文件中的目录文件

#nginx配置文件也支持include语法

6.2 增加一台虚拟主机:

[root@host conf]# cd vhost

[root@host vhost]# vim aaa.com.conf    //添加下面这一段

server
{
    listen 80 default_server;     //有'default_server'标记的就是默认虚拟主机
    server_name aaa.com;
    index index.html index.htm index.php;
    root /data/wwwroot/default;
}

[root@host vhost]# mkdir -p /data/wwwroot/default       //创建配置文件中指定的root目录

6.3 为虚拟主机添加内容

进入目录,添加索引页:

[root@host vhost]# cd /data/wwwroot/default

[root@host default]# vim index.html     //编辑一段话

This is the default directory.

[root@host default]# /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  

重启动或重加载(两个命令选一个):
[root@host default]# /usr/local/nginx/sbin/nginx -s reload   //重加载
[root@host default]# /usr/local/nginx/sbin/nginx restart       //重启动

6.4 检测

[root@host default]# curl localhost
This is the default directory
[root@host default]# curl -x127.0.0.1:80 123.com
This is the default directory

7. Nginx用户认证

7.1 创建一个虚拟主机

[root@host default]# cd  /usr/local/nginx/conf/vhost/
[root@host vhost]# vim test.com.conf      //写入如下内容

server
{
    listen 80;
    server_name test.com;
    index index.html index.htm index.php;
    root /data/wwwroot/test.com;

location  /       
# / 表示根目录,如果你改成 /admin/,那就是针对目录认证;/admin/test.php,针对php文件认证。
# 指定设置用户认证的目录(还可以设置对目录或者PHP的用户认证)
    {
        auth_basic              "Auth";
#指定用户名
        auth_basic_user_file  /usr/local/nginx/conf/htpasswd;
#指定用户的密码文件
     }
}

7.2 生成密码文件

[root@host vhost]# yum install -y httpd     //需要使用Apache的/usr/local/apache/bin/htpasswd命令,如果已经安装了Apache,可以直接使用,如果没有,需要yum安装
[root@host vhost]# htpasswd -c /usr/local/nginx/conf/htpasswd zhouqun
New password: 
Re-type new password: 
Adding password for user zhouqun
# htpasswd -c创建该密码文件,如果是第二次添加用户,不用加该 -c 选项,所添加的用户名和密码会保存到该文件下。

重新加载

[root@host vhost]# /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
[root@host vhost]# /usr/local/nginx/sbin/nginx -s reload
# 使用reload的好处是能避免因配置文件中存在错误而无法正常启动, reload不会破坏原有运行环境,所以不适用restart。

7.3 添加配置文件

[root@host vhost]# mkdir /data/wwwroot/test.com    //添加配置文件指定的根目录

[root@host vhost]# echo "This is test.com" >/data/wwwroot/test.com/index.html     //添加索引页

7.4 检查

[root@host vhost]# curl -x127.0.0.1:80 test.com -uzhouqun:123456
This is test.com

#如果不指定用户名和密码,会报错401,原因是:需要用户认证;
#如果为创建虚拟主机根目录会报错404,原因是:找不到指定目录;
#如果指定目录中没有添加索引页(.html或.php文件),会报错404,原因是:文件存在错误。

8. Nginx域名重定向

8.1 编辑虚拟主机配置文件

[root@host vhost]# vim test.com.conf

server
{
    listen 80;
    server_name test.com test2.com test3.com;
#为一个IP配置多个域名,此时权重会改变,如果需要全部跳转到第一个域名,可以使用rewrite模块实现
    index index.html index.htm index.php;
    root /data/wwwroot/test.com;
    if ($host != 'test.com' ) {
        rewrite  ^/(.*)$  http://test.com/$1  permanent;
    }
#使用rewrite模块编写跳转代码
# 实际上,rewrite  ^/(.*)$  http://test.com/$1  = rewrite  http://$host/(.*)$  http://test.com/$1
# ^代替了$host
}

[root@host vhost]# /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
[root@host vhost]# /usr/local/nginx/sbin/nginx -s reload

8.2 检测

[root@host vhost]# curl -x127.0.0.1:80 test2.com -I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.12.1
Date: Fri, 8 Sep 2017 1:20:24 GMT
Content-Type: text/html
Content-Length: 185
Connection: keep-alive
Location: http://test.com/

# 301, 域名跳转,跳转后的地址为  http://test.com/

9. nginx.conf 配置详解

完整的Nginx配置参数中文说明了。

#定义Nginx运行的用户和用户组
user www www;

#nginx进程数,建议设置为等于CPU总核心数。
worker_processes 8;

#全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]
error_log /var/log/nginx/error.log info;

#进程文件
pid /var/run/nginx.pid;

#一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(系统的值ulimit -n)与nginx进程数相除,但是nginx分配请求并不均匀,所以建议与ulimit -n的值保持一致。
worker_rlimit_nofile 65535;

#工作模式与连接数上限
events
{
#参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型,如果跑在FreeBSD上面,就用kqueue模型。
use epoll;
#单个进程最大连接数(最大连接数=连接数*进程数)
worker_connections 65535;
}

#设定http服务器
http
{
include mime.types; #文件扩展名与文件类型映射表
default_type application/octet-stream; #默认文件类型
#charset utf-8; #默认编码
server_names_hash_bucket_size 128; #服务器名字的hash表大小
client_header_buffer_size 32k; #上传文件大小限制
large_client_header_buffers 4 64k; #设定请求缓
client_max_body_size 8m; #设定请求缓
sendfile on; #开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
autoindex on; #开启目录列表访问,合适下载服务器,默认关闭。
tcp_nopush on; #防止网络阻塞
tcp_nodelay on; #防止网络阻塞
keepalive_timeout 120; #长连接超时时间,单位是秒

#FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。下面参数看字面意思都能理解。
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;

#gzip模块设置
gzip on; #开启gzip压缩输出
gzip_min_length 1k; #最小压缩文件大小
gzip_buffers 4 16k; #压缩缓冲区
gzip_http_version 1.0; #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
gzip_comp_level 2; #压缩等级
gzip_types text/plain application/x-javascript text/css application/xml;
#压缩类型,默认就已经包含text/html,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
gzip_vary on;
#limit_zone crawler $binary_remote_addr 10m; #开启限制IP连接数的时候需要使用

upstream blog.ha97.com {
#upstream的负载均衡,weight是权重,可以根据机器配置定义权重。weigth参数表示权值,权值越高被分配到的几率越大。
server 192.168.80.121:80 weight=3;
server 192.168.80.122:80 weight=2;
server 192.168.80.123:80 weight=3;
}

#虚拟主机的配置
server
{
#监听端口
listen 80;
#域名可以有多个,用空格隔开
server_name www.ha97.com ha97.com;
index index.html index.htm index.php;
root /data/www/ha97;
location ~ .*.(php|php5)?$
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
#图片缓存时间设置
location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 10d;
}
#JS和CSS缓存时间设置
location ~ .*.(js|css)?$
{
expires 1h;
}
#日志格式设定
log_format access '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $http_x_forwarded_for';
#定义本虚拟主机的访问日志
access_log /var/log/nginx/ha97access.log access;

#对 "/" 启用反向代理
location / {
proxy_pass http://127.0.0.1:88;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
#后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#以下是一些反向代理的配置,可选。
proxy_set_header Host $host;
client_max_body_size 10m; #允许客户端请求的最大单文件字节数
client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数,
proxy_connect_timeout 90; #nginx跟后端服务器连接超时时间(代理连接超时)
proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时)
proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收超时)
proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的设置
proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
proxy_temp_file_write_size 64k;
#设定缓存文件夹大小,大于这个值,将从upstream服务器传
}

#设定查看Nginx状态的地址
location /NginxStatus {
stub_status on;
access_log on;
auth_basic "NginxStatus";
auth_basic_user_file conf/htpasswd;
#htpasswd文件的内容可以用apache提供的htpasswd工具来产生。
}

#本地动静分离反向代理配置
#所有jsp的页面均交由tomcat或resin处理
location ~ .(jsp|jspx|do)?$ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8080;
}
#所有静态文件由nginx直接读取不经过tomcat或resin
location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$
{ expires 15d; }
location ~ .*.(js|css)?$
{ expires 1h; }
}
}

更详细的模块参数请参考:http://wiki.nginx.org/Main

LNMP架构 (1) 之 架构介绍、MySQL安装、PHP安装、Nginx介绍

1. LNMP架构介绍

LNMP代表的就是:Linux系统下Nginx+MySQL+PHP这种网站服务器架构。

未分类

  • 和LAMP不同的是,提供web服务的是Nginx
  • 并且php是作为一个独立服务存在的,这个服务叫做php-fpm
  • Nginx直接处理静态请求,动态请求会转发给php-fpm。

2. MySQL安装

2.1 卸载二进制包安装的MySQL

确认MySQL服务运行状态,并停止

[root@host ~]# ps -ef | grep mysql
[root@host ~]# /etc/init.d/mysql.server status
[root@host ~]# /etc/init.d/mysql.server stop

删除MySQL安装时的相关文件

[root@host ~]# rm -rf /usr/local/mysql 
[root@host ~]# rm -rf /etc/init.d/mysqld 
[root@host ~]# rm -rf /data/mysql

2.2 安装MySQL

和之前LAMP环境安装MySQL的方法一样 可以参考前面的文章 LAMP架构及安装配置(https://my.oschina.net/zhouyuntai/blog/1647058) 中的Mysql安装。

3. PHP安装

和LAMP安装PHP有区别,需要开启php-fpm服务。

3.1 准备PHP的包和用户

[root@host ~]# cd /usr/local/src/
[root@host src]# wget http://cn2.php.net/distributions/php-5.6.30.tar.gz   //下载php二进制包
[root@host src]# tar zxvf php-5.6.30.tar.gz   //解压缩
[root@host  src]# useradd -s /sbin/nologin php-fpm   //创建专门账号用来运行php-fpm服务,因为在LNMP环境中,PHP是以一种服务的形式独立存在的

3.2 卸载之前编译安装的PHP(如果之前有安装的话)

[root@host ~]# cd /usr/local/src
[root@host src]# ls
[root@host src]# cd php-5.6.30
[root@host php-5.6.30]# ls
[root@host php-5.6.30]# make clean

3.3 安装PHP

[root@host php-5.6.30]# cd php-5.6.30
[root@host php-5.6.30]# ./configure --prefix=/usr/local/php-fpm --with-config-file-path=/usr/local/php-fpm/etc --enable-fpm --with-fpm-user=php-fpm --with-fpm-group=php-fpm --with-mysql=/usr/local/mysql --with-mysqli=/usr/local/mysql/bin/mysql_config --with-pdo-mysql=/usr/local/mysql --with-mysql-sock=/tmp/mysql.sock --with-libxml-dir --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --with-iconv-dir --with-zlib-dir --with-mcrypt --enable-soap --enable-gd-native-ttf --enable-ftp --enable-mbstring --enable-exif --with-pear --with-curl  --with-openssl   //初始化

3.4 编译过程中的出错排查

错误1:

onfigure: error: xml2-config not found. Please check your libxml2 installation.

解决办法1:

[root@host php-5.6.30]# yum list |grep libxml2
libxml2.x86_64                          2.9.1-6.el7_2.3                @anaconda
libxml2.i686                            2.9.1-6.el7_2.3                base    
libxml2-devel.i686                      2.9.1-6.el7_2.3                base    
libxml2-devel.x86_64                    2.9.1-6.el7_2.3                base    
libxml2-python.x86_64                  2.9.1-6.el7_2.3                base    
libxml2-static.i686                    2.9.1-6.el7_2.3                base    
libxml2-static.x86_64                  2.9.1-6.el7_2.3                base    

[root@host php-5.6.30]# yum install -y libxml2 libxml2-devel     //一般只需要安裝devel的庫文件就好了

错误2:

configure: error: Cannot find OpenSSL's <evp.h>

解决办法2:

[root@host php-5.6.30]# yum install -y openssl openssl-devel

错误3:

configure: error: Please reinstall the libcurl distribution -
    easy.h should be in <curl-dir>/include/curl/

解决办法3:

[root@host php-5.6.30]# yum install -y libcurl libcurl-devel

错误4:

configure: error: jpeglib.h not found.

解决办法4:

[root@host php-5.6.30]# yum install -y libjpeg libjpeg-turbo-devel 

错误5:

configure: error: png.h not found.

解决办法5:

[root@host php-5.6.30]# yum install -y libpng libpng-devel

错误6:

configure: error: freetype-config not found.

解决办法6:

[root@host php-5.6.30]# yum install -y freetype freetype-devel

错误7:

configure: error: mcrypt.h not found. Please reinstall libmcrypt.

解决办法7:

[root@host php-5.6.30]# yum install -y libmcrypt libmcrypt-devel

错误8:

configure: error: mcrypt.h not found. Please reinstall libmcrypt.
(centos源不能安装libmcrypt-devel,由于版权的原因没有自带mcrypt的包rpm -qa|grep limcrypt limcrypt-devel,此源为rethot社区版的源)

解决办法8:安装第三方yum源

wget http://www.atomicorp.com/installers/atomic
sh ./atomic

yum  install  php-mcrypt  libmcrypt  libmcrypt-devel

检测、编译和安装

[root@host php-5.6.30]# echo $?
0

[root@host php-5.6.30]# make 

[root@host php-5.6.30]# make install

3.5 配置PHP

添加配置文件

[root@host php-5.6.30]# cp php.ini-production /usr/local/php-fpm/etc/php.ini

配置文件编辑

[root@host php-5.6.30]# vi /usr/local/php/etc/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,本地监听,也可以监听其他IP:port
#此处格式会影响配置Nginx和PHP结合时Nginx寻址PHP的路径
listen.mode = 666
#当监听的为socket文件时该部分才生效,用于指定.sock文件的权限
user = php-fpm
group = php-fpm
#定义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
#以上部分为进程相关信息

配置启动脚本

[root@host etc]# cd /usr/local/src/php-5.6.30  //进入源码目录下来

[root@host php-5.6.30]#  cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm  //把启动脚本放到到系统配置

[root@host php-5.6.30]# chmod 755 /etc/init.d/php-fpm  //修改权限

[root@host php-5.6.30]# chkconfig --add php-fpm  //添加到开机启动项

[root@host php-5.6.30]# chkconfig php-fpm on  //设置开机启动

[root@host php-5.6.30]# service php-fpm start  //启动php-fpm服务
Starting php-fpm  done

[root@host php-5.6.30]# ps aux |grep php-fpm  //查看后台www的pool是否启动

4. Nginx介绍

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

  • Nginx官网 nginx.org,最新版1.13,最新稳定版1.12
  • Nginx应用场景:web服务、反向代理、负载均衡
  • Nginx著名分支,淘宝基于Nginx开发的Tengine,使用上和Nginx一致,服务名,配置文件名都一样,和Nginx的最大区别在于Tenging增加了一些定制化模块,在安全限速方面表现突出,另外它支持对js,css合并
  • Nginx核心+lua相关的组件和模块组成了一个支持lua的高性能web容器openresty。

1、Nginx优点 Nginx设计为一个主进程多个工作进程的工作模式,每个进程是单线程来处理多个连接,而且每个工作进程采用了非阻塞I/O来处理多个连接,从而减少了线程上下文切换,从而实现了公认的高性能、高并发;因此在生成环境中会通过把CPU绑定给Nginx工作进程从而提升其性能;另外因为单线程工作模式的特点,内存占用就非常少了。 Nginx更改配置重启速度非常快,可以毫秒级,而且支持不停止Nginx进行升级Nginx版本、动态重载Nginx配置。 Nginx模块也是非常多,功能也很强劲,不仅可以作为http负载均衡,Nginx发布1.9.0版本还支持TCP负载均衡,还可以很容易的实现内容缓存、web服务器、反向代理、访问控制等功能。

2、Lua的优点 Lua是一种轻量级、可嵌入式的脚本语言,这样可以非常容易的嵌入到其他语言中使用。另外Lua提供了协程并发,即以同步调用的方式进行异步执行,从而实现并发,比起回调机制的并发来说代码更容易编写和理解,排查问题也会容易。Lua还提供了闭包机制,函数可以作为First Class Value 进行参数传递,另外其实现了标记清除垃圾收集。 因为Lua的小巧轻量级,可以在Nginx中嵌入Lua VM,请求的时候创建一个VM,请求结束的时候回收VM。

3、什么是ngx_lua ngx_lua是Nginx的一个模块,将Lua嵌入到Nginx中,从而可以使用Lua来编写脚本,这样就可以使用Lua编写应用脚本,部署到Nginx中运行,即Nginx变成了一个Web容器;这样开发人员就可以使用Lua语言开发高性能Web应用了。 ngx_lua提供了与Nginx交互的很多的API,对于开发人员来说只需要学习这些API就可以进行功能开发,而对于开发web应用来说,如果接触过Servlet的话,其开发和Servlet类似,无外乎就是知道接收请求、参数解析、功能处理、返回响应这几步的API是什么样子的。

4、开发环境 我们可以使用OpenResty来搭建开发环境,OpenResty将Nginx核心、LuaJIT、许多有用的Lua库和Nginx第三方模块打包在一起;这样开发人员只需要安装OpenResty,不需要了解Nginx核心和写复杂的C/C++模块就可以,只需要使用Lua语言进行Web应用开发了。

KVM虚拟化-qemu-kvm杂记

一、安装KVM

1、VMware Workstation开启虚拟化功能

未分类

1.1 查看自己的物理CPU是否支持硬件辅助虚拟化

只要标记有vmx或svm,就说明支持硬件虚拟化
[root@node2 ~]# grep -E --color=auto "(vmx|svm)" /proc/cpuinfo 
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts mmx fxsr sse sse2 ss syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq vmx ssse3 cx16 pcid sse4_1 sse4_2 x2apic popcnt xsave hypervisor lahf_lm arat epb pln pts dts tpr_shadow vnmi ept vpid fsgsbase smep
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts mmx fxsr sse sse2 ss syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology tsc_reliable nonstop_tsc aperfmperf unfair_spinlock pni pclmulqdq vmx ssse3 cx16 pcid sse4_1 sse4_2 x2apic popcnt xsave hypervisor lahf_lm arat epb pln pts dts tpr_shadow vnmi ept vpid fsgsbase smep

2、安装kvm

2.1 装载kvm模块

装载kvm核心模块:

[root@node2 ~]# modprobe kvm

因为我是Intel的CPU,所以装载intel的kvm模块:
[root@node2 ~]# modprobe kvm-intel

2.2 查看装载模块

此时内核已经成为kvm-hypervisor
[root@node2 ~]# lsmod | grep kvm
kvm_intel              55496  0 
kvm                   337772  1 kvm_intel
[root@node2 ~]# 

验证是否有KVM文件,存在说明内核已经被kvm寄宿了
[root@node2 ~]# ll /dev/kvm 
crw-rw---- 1 root root 10, 232 Sep 15 23:14 /dev/kvm

2.3 查看虚拟化管理包组

查看包组:
[root@node2 ~]# yum grouplist | grep -i "virtualization"
   Virtualization
   Virtualization Client
   Virtualization Platform
   Virtualization Tools

2.4 由于我们暂时先学习qemu管理虚拟机,只安装 Virtualization包组里的qemu组件即可

[root@node2 ~]# yum install qemu-kvm

2.5 查看qemu的文件

[root@node2 ~]# rpm -ql qemu-kvm | grep qemu-kvm | head -2

2.6 执行程序位置不在环境变量下,需要创建链接

[root@node2 ~]# ln -sv /usr/libexec/qemu-kvm /usr/bin/
`/usr/bin/qemu-kvm' -> `/usr/libexec/qemu-kvm'

3、CentOS7的虚拟化包组

只要安装Virtualization包组即可

[root@master1 ~]# yum grouplist | grep -i "virtualization"
   Virtualization Host
   Virtualization

3.1 CentOS7安装KVM

装载kvm
# modprobe kvm
# modprobe kvm-intel

查看kvm模块:
modinfo kvm
[root@master1 ~]# modinfo kvm-intel

二、qemu-kvm虚拟机管理(CentOS7)

1、安装qemu

[root@master1 ~]# yum install qemu-kvm

1.1 创建软链接

[root@master1 ~]# rpm -ql qemu-kvm | grep /libexec/
/usr/libexec/qemu-kvm

[root@master1 ~]# ln -sv /usr/libexec/qemu-kvm /usr/bin/
‘/usr/bin/qemu-kvm’ -> ‘/usr/libexec/qemu-kvm’

1.2 查看使用帮助

[root@master1 ~]# qemu-kvm -h

2、创建一个简单的虚拟机

2.1 去互联网搜索开源的镜像文件

访问:https://launchpad.net/cirros

查看该网站发现只更新到0.33,获取源码已经移交到github托管。这边下载0.30做实验

[root@master1 ~]# ls
cirros-no_cloud-0.3.0-x86_64-disk.img

2.1.1 查看磁盘映像文件格式

[root@master1 ~]# qemu-img info /root/cirros-no_cloud-0.3.0-x86_64-disk.img 
image: /root/cirros-no_cloud-0.3.0-x86_64-disk.img
file format: qcow2
virtual size: 39M (41126400 bytes)
disk size: 11M
cluster_size: 65536
Format specific information:
    compat: 0.10

2.2 启动微缩版虚拟机

内存128M,CPU 1个
[root@master1 ~]# qemu-kvm -m 128 -smp 1 -name "test" -hda cirros-no_cloud-0.3.0-i386-disk.img 
VNC server running on `::1:5900'

2.2.2 默认用VNC打开,需要在宿主机安装一个VNC客户端进行查看

Centos7需要先安装图形界面,并切换到图形界面
yum groupinstall "GNOME Desktop" "Graphical Administration Tools"

查看运行级别:
[root@master1 ~]# systemctl get-default
multi-user.target

修改运行级别为图形化界面:
systemctl set-default graphical.target
或者
ln -s /lib/systemd/system/runlevel5.target /etc/systemd/system/default.target

运行图形界面:
startx &

还是需要重启宿主机,才能转发X11图形调用到xmanager
# reboot

安装vnc客户端:
[root@master1 ~]# yum install tigervnc

连接虚拟机:
[root@master1 ~]# vncviewer :5900

未分类

未分类

切换为管理员

未分类

切换qemu监控接口:Ctrl+Alt+2

未分类

显示当前虚拟机的名字

未分类

显示当前虚拟机的状态

未分类

虚拟机切换回命令行:Ctrl+Alt+1

未分类

关闭虚拟机,不是断电,而是向里面发送关机信号:

[root@master1 ~]# ps aux | grep qemu-kvm
root      2504 36.5  1.6 561512 65812 pts/0    Sl+  19:03   0:24 qemu-kvm -m 128 -smp 1 -name test -hda cirros-no_cloud-0.3.0-i386-disk.img
root      2539  0.0  0.0 112660   976 pts/1    S+   19:04   0:00 grep --color=auto qemu-kvm
[root@master1 ~]# 
[root@master1 ~]# kill -9 2504

2.2.3 杂项

查看可以模拟的主机类型:
[root@master1 ~]# qemu-kvm -M ?

查看可以模拟的CPU类型:
[root@master1 ~]# qemu-kvm -cpu ?

默认模拟的是QEMU的虚拟CPU,不是底层硬件CPU

未分类

想要启动虚拟机时,模拟底层硬件CPU需要加-cpu参数:

[root@master1 ~]# qemu-kvm -m 128 -cpu host -smp 1 -name "test" -hda cirros-no_cloud-0.3.0-i386-disk.img 

未分类

3、选项

3.1 device

磁盘映像高级选项:
[root@master1 ~]# qemu-kvm -m 128 -cpu host -smp 1 -name "test" -drive file=cirros-no_cloud-0.3.0-i386-disk.img,if=virtio,media=disk,format=qcow2,cache=writeback

硬盘格式已经显示为VDA

未分类

未分类

3.1.1 安装window-xp

[root@master1 ~]# ls -lht xp.iso 
-rw-r--r-- 1 root root 499M Mar 17 20:17 xp.iso

创建目录:
[root@master1 ~]# mkdir -pv /images/windows/

创建磁盘映像文件(20G大小,磁盘类型为元数据类型【稀疏格式】):
[root@master1 ~]# qemu-img create -o size=20G,preallocation=metadata -f qcow2 /images/windows/winxp.qcow2
[root@master1 ~]# ll -lht /images/windows/winxp.qcow2 
-rw-r--r-- 1 root root 21G Mar 17 21:01 /images/windows/winxp.qcow2
[root@master1 ~]# du -sh /images/windows/winxp.qcow2 
4.1M    /images/windows/winxp.qcow2

启动安装window-xp(512内存,1核CPU,CPU使用底层硬件模拟,使用XP镜像安装,启动顺序为光盘-硬盘,第一次重启剔除光盘启动)
[root@master1 ~]# qemu-kvm -m 512 -smp 1 -cpu host -drive file=/images/windows/winxp.qcow2,media=disk -drive file=/root/xp.iso,media=cdrom -boot order=dc,once=d

登陆VNC查看:

[root@master1 ~]# vncviewer :5900

未分类

未分类

安装系统中

未分类

4、KVM-显示

4.1 SDL功能

[root@master1 ~]# yum install -y SDL SDL-devel SDL-static

[root@master1 ~]# qemu-kvm -m 128 -smp 1 -name "test" -hda cirros-no_cloud-0.3.0-i386-disk.img -sdl
SDL support is disabled

由于qemu-kvm编译默认没有加入SDL功能,所以该实验跳过

4.2 vnc更改监听端口5901

默认0号面板端口为5900,以此类推
[root@master1 ~]# qemu-kvm -m 128 -cpu host -smp 1 -name "test" -drive file=cirros-no_cloud-0.3.0-i386-disk.img,if=virtio,media=disk,format=qcow2,cache=writeback -vnc 10.201.106.131:1

[root@master1 ~]# vncviewer 10.201.106.131:5901

未分类

4.3 启动虚拟机直接显示monitor控制台设置VNC密码

[root@master1 ~]# qemu-kvm -m 128 -cpu host -smp 1 -name "test" -drive file=cirros-no_cloud-0.3.0-i386-disk.img,if=virtio,media=disk,format=qcow2,cache=writeback -vnc 10.201.106.131:1,password -monitor stdio
QEMU 1.5.3 monitor - type 'help' for more information
(qemu) 

设置VNC密码
(qemu) change vnc password
Password: ******

4.4 通过VNC密码登陆

[root@master1 ~]# qemu-kvm -m 128 -cpu host -smp 1 -name "test" -drive file=cirros-no_cloud-0.3.0-i386-disk.img,if=virtio,media=disk,format=qcow2,cache=writeback -vnc 10.201.106.131:1,password

未分类

未分类

4.4.1 控制台切换

未分类

切换控制台或系统界面
Ctrl+a,c

未分类

显示控制台帮助:Ctrl+a,h

C-a h    print this help
C-a x    exit emulator
C-a s    save disk data back to file (if -snapshot)
C-a t    toggle console timestamps
C-a b    send break (magic sysrq)
C-a c    switch between console and monitor
C-a C-a  sends C-a

4.4.2 指定显卡接口类型

[root@master1 ~]# qemu-kvm -m 128 -cpu host -smp 1 -name "test" -drive file=cirros-no_cloud-0.3.0-i386-disk.img,if=virtio,media=disk,format=qcow2,cache=writeback -nographic -vga cirrus

5、网络

5.1 创建管理桥

查看桥模块,桥是在内核中实现的:
[root@master1 ~]# modinfo bridge

安装桥管理命令:
# yum install -y bridge-utils

查看其文件路径:
[root@master1 ~]# rpm -ql bridge-utils

创建桥:
[root@master1 ~]# brctl addbr br0

关闭桥:
[root@master1 ~]# brctl stp br0 off
[root@master1 ~]# brctl show

启动桥:
[root@master1 ~]# ip link set br0 up

其他:可以用nmtui图形界面添加桥
# nmtui

5.2 网卡

5.2.1 查看当前支持的网卡类型

[root@master1 ~]# qemu-kvm -net nic,model=?
qemu: Supported NIC models: ne2k_pci,i82551,i82557b,i82559er,rtl8139,e1000,pcnet,virtio

5.2.2 启动虚拟机指定网卡类型

[root@master1 ~]# qemu-kvm -m 128 -cpu host -smp 1 -name "test" -drive file=cirros-no_cloud-0.3.0-i386-disk.img,if=virtio,media=disk,format=qcow2,cache=writeback -nographic -net nic -net tap,ifname=vif0.0,script=no

内部的系统网卡类型默认是e1000
# lsmod | grep e1000
e1000                 101773  0 

设置宿主机的后端网卡
首先配置启动和关闭脚本:
[root@master1 ~]# vim /etc/qemu-ifup 

#!/bin/bash
#
bridge=br0

if [ -n "$1"  ]; then
    ip link set $1 up
    brctl addif $bridge $1
    [ $? -eq 0 ] && exit 0 || exit 1
else
    echo "Error,no interface specified"
    exit 1
fi

[root@master1 ~]# chmod +x /etc/qemu-ifup

启动测试:
[root@master1 ~]# qemu-kvm -m 128 -cpu host -smp 1 -name "test" -drive file=cirros-no_cloud-0.3.0-i386-disk.img,if=virtio,media=disk,format=qcow2,cache=writeback -nographic -net nic -net tap,ifname=vif0.0,script=/etc/qemu-ifup

[root@master1 ~]# brctl show
bridge name bridge id       STP enabled interfaces
br0     8000.66fc76ef2ced   no      vif0.0

5.3 开启第二台虚拟机

[root@master1 ~]# qemu-kvm -m 128 -cpu host -smp 1 -name "test1" -drive file=cirros-no_cloud-0.3.0-i386-disk.img,if=virtio,media=disk,format=qcow2,cache=writeback -nographic -net nic -net tap,ifname=vif1.0,script=/etc/qemu-ifup

[root@master1 ~]# brctl show
bridge name bridge id       STP enabled interfaces
br0     8000.66fc76ef2ced   no      vif0.0
                            vif1.0

5.4 配置两台虚拟机IP为同个网段通信(隔离网络模型)

# hostname
test
# ifconfig eth0 192.168.1.1/24

# hostname
test1
# ifconfig eth0 192.168.1.2/24

不通,原因是MAC地址相同,需要随机生成:

[root@master1 ~]# qemu-kvm -m 128 -cpu host -smp 1 -name "test1" -drive file=cirros-no_cloud-0.3.0-i386-disk.img,if=virtio,media=disk,format=qcow2,cache=writeback -nographic -net nic,macaddr=52:54:00:12:34:57 -net tap,ifname=vif1.0,script=/etc/qemu-ifup

网络可以通了:

未分类

5.5 (路由网络模型)

5.5.1 宿主机添加虚拟网卡

[root@master1 ~]# ip link add veth0.0 type veth peer veth1.0

[root@master1 ~]# ifconfig -a | grep veth
veth0: flags=4098<BROADCAST,MULTICAST>  mtu 1500
veth1.0: flags=4098<BROADCAST,MULTICAST>  mtu 1500

veth0留在物理机,veth1添加到br0

激活两块网卡:
[root@master1 ~]# ip link set veth0 up
[root@master1 ~]# ip link set veth1.0 up

将vet1.0添加至br0
[root@master1 ~]# brctl addif br0 veth1.0
[root@master1 ~]# brctl show
bridge name bridge id       STP enabled interfaces
br0     8000.c2e8d51d8e78   no      veth1.0

[root@master1 ~]# ifconfig veth0 192.168.1.254/24

在KVM上的虚拟机测试ping
# hostname
test1
# ping 192.168.1.254
PING 192.168.1.254 (192.168.1.254): 56 data bytes
64 bytes from 192.168.1.254: seq=0 ttl=64 time=13.576 ms
64 bytes from 192.168.1.254: seq=1 ttl=64 time=2.025 ms

KVM客户机添加去往物理机地址的网关:
# route add default gw 192.168.1.254
已经可以ping通物理机:
# ping 10.201.106.131
PING 10.201.106.131 (10.201.106.131): 56 data bytes
64 bytes from 10.201.106.131: seq=0 ttl=64 time=1.828 ms
64 bytes from 10.201.106.131: seq=1 ttl=64 time=2.080 ms

5.6 路由网络模型

5.6.1 物理机打开路由转发

[root@master1 ~]# cat /proc/sys/net/ipv4/ip_forward
0

[root@master1 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward

但是这时候还是通不了外网,因为包发出去回不来:

未分类

未分类

5.6.2 使用nat模式转发到外网

root@master1 ~]# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 ! -d 192.168.1.0/24 -o eth0 -j SNAT --to-source 10.201.106.131

KVM虚拟机已经可以ping通外网

未分类

未分类

5.6.3 上面方式太繁琐,多了一层虚拟桥,其实只需把网关地址配置到br0即可实现外网转发

[root@master1 ~]# ip link set veth0 down
[root@master1 ~]# ip link set veth1.0 down

[root@master1 ~]# ifconfig br0 192.168.1.254/24 up

KVM测试外网联通性:
# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=127 time=72.507 ms
64 bytes from 8.8.8.8: seq=1 ttl=127 time=114.481 ms

抓包,br0上没有转换

未分类

是在物理网卡eth0转换的

未分类

5.7 桥接模型

5.7.1 取消之前br0地址

[root@master1 ~]# ip addr del 192.168.1.254/24 dev br0

5.7.2 把物理网卡添加到br0

一旦物理网卡添加到br0,物理网卡就变成了交换机

首先拆除物理网卡地址,然后将物理网卡添加至br0,最后在br0配置原先的物理网卡的IP地址。由于担心xshell断掉,直接在终端操作:

未分类

[root@master1 ~]# brctl show
bridge name bridge id       STP enabled interfaces
br0     8000.000c29a77aec   no      eth0
                            vif0.0
                            vif1.0

5.7.3 KVM虚拟机配置跟宿主机同个网段IP和网关

# ifconfig eth0 10.201.106.81/24
# route add default gw 10.201.106.2

# ifconfig eth0 10.201.106.82/24
# route add default gw 10.201.106.2

又可以ping通外网了:

未分类

抓包物理机网卡,源地址全是KVM虚拟机IP发出的包:

未分类

5.8 一旦KVM虚拟机停止,网卡会自动删除

关机前:
bridge name bridge id       STP enabled interfaces
br0     8000.000c29a77aec   no      eth0
                            vif0.0
关机                          vif1.0
# poweroff

会自动拆除网卡:
[root@master1 ~]# brctl show
bridge name bridge id       STP enabled interfaces
br0     8000.000c29a77aec   no      eth0
                            vif1.0

6、基于PXE环境安装虚拟机

6.1 创建映像文件

[root@master1 ~]# mkdir /images/centos

[root@master1 ~]# qemu-img create /images/centos/centos6.img -o size=120G,preallocation=metadata -f qcow2

6.2 启动虚拟机

[root@master1 ~]# qemu-kvm -m 512 -smp 1 -name centos -drive file=/images/centos/centos6.img,media=disk,if=virtio -net nic,model=virtio,macaddr=52:54:00:66:66:66 -net tap,ifname=centos6.0,script=/etc/qemu-ifup -boot order=nc,once=n

我没有PXE环境,所以一直是获取IP地址界面

未分类

7、其他操作

7.1 用光盘方式安装一个CentOS6.6

[root@master1 ~]# qemu-kvm -m 512 -smp 1 -name centos -drive file=/images/centos/centos6.img,media=disk,if=virtio -drive file=/root/centos6.iso,media=cdrom -boot order=dc,once=d -net nic,model=virtio,macaddr=52:54:00:66:66:66 -net tap,ifname=centos6.0,script=/etc/qemu-ifup

安装完毕查看模块,网卡等设备是半虚拟化的virtio

未分类

7.2 宿主机热迁移,需要共享存储

在待迁入目的宿主机使用(指定哪个端口接收待迁移虚拟机进入)
    # qemu-kvm -vnc :N -incoming tcp:0:7777
    # vncviewer :590N

在源主机使用monitor接口,指定要迁入的宿主机信息:
        migrate tcp:DEST_IP:DEST:PORT

7.3 切换至控制台

Ctrl+Alt+2 切换至控制台

Ctrl+Alt+1 切换回系统操作界面

未分类

7.3.1 查看当前虚拟机CPU信息

CPU是用线程模拟的

未分类

7.3.2 qemu缺陷,无法远程管理虚拟机

Tomcat 安装配置与优化

什么是 Tomcat

Tomcat 是 Java web 服务器中使用最广的中间件,jsp 必须要使用类似 Tomcat 这样的程序进行解析。

Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。 Tomcat 是一个轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应对HTML 页面的访问请求。实际上Tomcat 部分是Apache 服务器的扩展,但它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。

安装 Java

1、下载

wget -c http://file201503.oss-cn-shanghai.aliyuncs.com/ftp/jdk-8u151-linux-x64.tar.gz

2、解压后放到/usr/local/下

mv jdk1.8.0_151/ /usr/local/jdk18  

3、配置环境变量

vim /etc/profile  

输入

export JAVA_HOME=/usr/local/jdk18
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar 

保存后执行

source /etc/profile    

安装 Tomcat

1、打开官网下载

未分类

wget -c http://supergsego.com/apache/tomcat/tomcat-8/v8.5.29/bin/apache-tomcat-8.5.29.tar.gz

解压后复制3份分别为 Tomcat1 Tomcat2 Tomcat3

[root@centos ~]# cd /usr/local/tomcat
tomcat1/ tomcat2/ tomcat3/

分别修改3个目录下 conf 下的 server.xml 端口为 8080、8081、8082

<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

启动 3 个 Tomcat

[root@centos bin]# ./catalina.sh start
Using CATALINA_BASE:   /usr/local/tomcat1
Using CATALINA_HOME:   /usr/local/tomcat1
Using CATALINA_TMPDIR: /usr/local/tomcat1/temp
Using JRE_HOME:        /usr/local/jdk18
Using CLASSPATH:       /usr/local/tomcat1/bin/bootstrap.jar:/usr/local/tomcat1/bin/tomcat-juli.jar
Tomcat started.

Tomcat 目录说明:

bin:二进制执行文件。里面最常用的文件是startup.bat,如果是 Linux 或 Mac 系统启动文件为 startup.sh。
conf:配置目录。里面最核心的文件是server.xml。可以在里面改端口号等。默认端口号是8080,也就是说,此端口号不能被其他应用程序占用。
lib:库文件。tomcat运行时需要的jar包所在的目录
logs:日志
temp:临时产生的文件,即缓存
webapps:web的应用程序。web应用放置到此目录下浏览器可以直接访问
work:编译以后的class文件。

Tomcat 自身配置域名和80端口访问

如果要使用80端口访问域名则配置

<Connector port="80" protocol="HTTP/1.1"
             connectionTimeout="20000"
             redirectPort="8443" />

         ……

<Host name="www.v5linux.com"  appBase="webapps"
          unpackWARs="true" autoDeploy="true">

      <!-- SingleSignOn valve, share authentication between web applications
           Documentation at: /docs/config/valve.html -->
      <!--
      <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
      -->

      <!-- Access log processes all example.
           Documentation at: /docs/config/valve.html
           Note: The pattern used is equivalent to using pattern="common" -->
      <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
             prefix="localhost_access_log" suffix=".txt"
             pattern="%h %l %u %t &quot;%r&quot; %s %b" />
       <Context docBase="/data/" path="" debug="0"  reloadable="true"/>
    </Host>

配置 nginx 代理多Tomcat 访问

在 nginx http 段加入

http {
    upstream tomcatcluster {
    ip_hash;
        server 127.0.0.1:8080;
        server 127.0.0.1:8081;
        server 127.0.0.1:8082;
   }
   ……

在 server 段配置,这里我配置了80端口跳443,并且加了 ssl 证书

    server {
    listen  80;
    server_name _;
    server_name www.v5linux.com v5linux.com;
    if ($request_method !~ ^(GET|HEAD|POST)$ ) {
            return        444;
        }
    rewrite ^(.*)$  https://www.v5linux.com$1 permanent;
}
    server {
        listen       443;
        server_name  www.v5linux.com;
        ssl on;
        ssl_certificate //usr/local/nginx/ssl/v5linux/fullchain.cer;
        ssl_certificate_key /usr/local/nginx/ssl/v5linux/v5linux.key;
        ssl_ciphers                EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
        ssl_prefer_server_ciphers  on;
        ssl_protocols              TLSv1.2;
        ssl_session_cache          shared:SSL:50m;
        ssl_session_timeout        1d;
        ssl_session_tickets        on;
        resolver                   114.114.114.114 valid=300s;
        resolver_timeout           10s;

        access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
            proxy_pass http://tomcatcluster;
        }

    }

开放防火墙

iptables -A INPUT -p tcp --dport 443 -j ACCEPT

做好解析,并确认

# dig www.v5linux.com

; <<>> DiG 9.10.6 <<>> www.v5linux.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62933
;; flags: qr aa rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.v5linux.com.        IN    A

;; ANSWER SECTION:
www.v5linux.com.    0    IN    A    59.111.92.121

;; Query time: 12 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Apr 04 14:00:14 CST 2018
;; MSG SIZE  rcvd: 49

浏览器访问

未分类

发现没有问题

Tomcat 自身配 ssl 证书,可以在 server.xml 中这段进行配置

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
            maxThreads="150" SSLEnabled="true">
     <SSLHostConfig>
         <Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
                      type="RSA" />
     </SSLHostConfig>
 </Connector>

Tomcat 默认的路径是在 Tomcat 的目录下的 webapps ,可以在配置文件中修改

<Host name="localhost"  appBase="webapps"
          unpackWARs="true" autoDeploy="true">

我们将其修改为

未分类

<Context docBase="/data/" path="" debug="0"  reloadable="true"/>    

创建 data 目录

mkdir /data/

然后新建一个 jsp 文件

 <%@ page contentType="text/html;charset=UTF-8" %>
<%
out.print("test");
%> 

访问

未分类

优化

  • java.lang.OutOfMemoryError: Java heap space异常
    表示堆内存空间满了,如果不是程序逻辑的bug,可能是因为项目中引用的jar比较多,导到内存溢出。JVM默认堆的最小使用内存为物理内存的1/64,最大使用内存为物理内存的1/4,如8G的物理内存,JVM默认堆的最小和最大内存分别为128m和2048m。通过调整JVM的-Xms(初始内存)和-Xmx(最大内存)两个参数加大内存使用限制。
  • java.lang.OutOfMemoryError: PermGen space异常
    表示静态内存区满了,通常是由于加载的类过多导致。jdk8以下版本通过修改JVM的-XX:PermSize和-XX:MaxPermSize两个参数,限制静态区最小和最大内存范围。jdk8改变了内存模型,将类定义存放到了元数据(MetaspaceSize)空间,而元数据空间是与堆空间共享同一块内存区域的,所以在JDK8以后版本不会存在PermGen space异常了,故不用设置此参数。
  • java.lang.StackOverflowError异常
    表示栈内存溢出。通常是由于死循环、无限递归导致。

修改Tomcat的内存配置,打开$TOMCAT_HOME/bin/catalina.sh文件(Windows系统是catalina.bat文件),大楖在250行左右,在JAVA_OPTS参数上添加内存参数设置即可。完整的JVM参数设置如下所示:

JAVA_OPTS="$JAVA_OPTS -server -Xms2048m -Xmx2048m -XX:PermSize=128m -XX:MaxPermSize=256 -Djava.awt.headless=true"

-server参数:表示以服务模式启动,启动速度会稍微慢一点,但性能会高很多。不加这个参数,默认是以客户端模式启动。
java.awt.headless=true参数:与图形操作有关,适用于linux系统。如生成验证码,含义是当前使用的是没有安装图安装图形界面的服务器,应用中如果获取系统显示有关参数会抛异常,可通过jmap -heap proccess_id查看设置是否成功。

未分类

修改后

未分类

并发配置优化

主要配置Tomcat能处理的请求数,当一个进程的线程数超过500个的话,那么这个进程的运行效率就很低了。表面上看线程越多处理的请求越多,其实过多的线程会占用CPU在不同线程之间切换的资源,导致CPU在每个线程上处理的时间片极期有限,反而会降低服务器的响应性能。

<Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol"
               connectionTimeout="20000"
               redirectPort="8443" 

                maxThreads="500"
                minSpareThreads="100"
                maxSpareThreads="200"
                acceptCount="200"
                maxIdleTime="30000"
                enableLookups="false"
               />

Tomcat的并发请求处理数量=maxThreads + acceptCount

  • maxThreads:最大能接受的请求数,默认为200
  • minSpareThreads:最少备用线程数,默认初始化,默认为25
  • maxSpareThreads:最多备用线程数,一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程
  • acceptCount:等待处理的请求队列,默认为100,超过队列长度,服务器则拒绝客户端请求,直接返回403
  • maxIdleTime:如果一个线程在30秒以内没有活跃,则终止运行并从线程池中移除。除非线程池数量小于或等于minSpareThreads数量。默认值是1分钟
  • enableLookups:如果为true,调用request.getRemoteHost会执行DNS反查,反向解析IP对应的域名或主机,效率较低,建议设为false。

更多参数设置,请参考Tomcat官方文档:http://tomcat.apache.org/tomcat-8.0-doc/config/http.html

Tomcat控制台总是打印日志问题的解决办法

问题

使用gradle启动项目,在tomcat控制台中不停地打印perf4j性能日志,导致开发过程很卡很慢。明明修改了logback.xml配置文件,让它输出到log文件中,而不是控制台,但是不起作用。

未分类

在Windows系统中,在启动tomcat后会出现上图这样的情况,

在ubuntu系统中,没有这种情况,应该是在ubuntu系统中,没有tomcat的控制台吧。
同样,部署在线上的时候也没有问题。

唯独在windows中进行开发的时候有问题。

解决过程

真的是尝试很久很久。

  • 刚开始调整日志打印路径,无果;
  • 然后就是调整日志打印级别,只打印Error的,这个实现了,却仍然打印;
  • 最后决定替换tomcat的Jar包里的代码,不让它打印日志了,解决问题。

Jar包中性能打印的语句为:

StopWatch stopWatch = new Log4JStopWatch("Messages.searchFiles");
try {
  ......
} finally {
  stopWatch.stop();
}

调用的perf4j-*.jar包中的方法

public Log4JStopWatch(String tag) {
  this(tag, null, Logger.getLogger(DEFAULT_LOGGER_NAME), Level.INFO, Level.WARN);
}

而这个方法最终打印在控制台上的语句为:

protected void log(String stopWatchAsString, Throwable exception) {
  logger.log((exception == null) ? normalPriority : exceptionPriority, stopWatchAsString, exception);
}

再跟踪这个方法,跳转到了log4j-*.jar包中的 Category.java类中的log 方法

public void log(Priority priority, Object message, Throwable t) {
  if(repository.isDisabled(priority.level)) {
    return;
  }
  if(priority.isGreaterOrEqual(this.getEffectiveLevel()))
  forcedLog(FQCN, priority, message, t);
}

再跳转时:

protected void forcedLog(String fqcn, Priority level, Object message, Throwable t) {
  callAppenders(new LoggingEvent(fqcn, this, level, message, t));
}

再往后就是具体打印的方法了。

之前问题的所有打印日志的方法都会走到这里,于是我把这个jar包中的log方法和forcedLog方法的内容都删除了,然后替换原来的log4j-*.jar包,实现效果。

这里提供一个修改后的jar包:

链接:https://pan.baidu.com/s/1078F50P8UuWW-Hgxt36QbQ 密码:j4w9

但如果是maven项目,不能直接替换jar包,可以根据tomcat的加载优先级,将修改后的jar包放到tomcat 中的lib 目录下进行覆盖。

Ubuntu Docker 配置 Tomcat 和 Nginx 使用 HTTPS 访问

安装 Docker

使用脚本自动安装

curl -fsSL get.docker.com -o get-docker.sh
sudo sh get-docker.sh --mirror Aliyun

更改镜像地址

  • 修改或新建 /etc/docker/daemon.json
{
  "registry-mirrors": [
    "https://registry.docker-cn.com"
  ]
}

启动 Docker

sudo systemctl daemon-reload
sudo systemctl enable docker
sudo systemctl start docker

配置 Tomcat

启动 Tomcat 容器

docker pull tomcat
docker run --name tomcat -d -p 8080:8080 tomcat

修改 Tomcat Manager 应用

docker exec -it tomcat /bin/bash
  • 修改 webapps/manager/META-INF/content.xml,允许需要的IP访问,这里运行所有的IP访问
<Context antiResourceLocking="false" privileged="true" >
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="^.*$" />
  <Manager sessionAttributeValueClassNameFilter="java.lang.(?:Boolean|Integer|Long|Number|String)|org.apache.catalina.filters.CsrfPreventionFilter$LruCache(?:$1)?|java.util.(?:Linked)?HashMap"/>
</Context>

配置 Tomcat 用户

  • 修改 conf/tomcat-user.xml,添加用户
<role rolename="admin-gui"/>
<role rolename="manager-gui"/>
<user username="tomcat" password="tomcat" roles="manager-gui,admin-gui"/>

配置 Nginx

配置目录

  • 新建目录 /home/ubuntu/hellowood/dev/nginx/conf, /home/ubuntu/hellowood/dev/nginx/log, /home/ubuntu/hellowood/dev/nginx/certs
  • 下载并解压相应的Nginx证书文件到 /home/ubuntu/hellowood/dev/nginx/conf

添加 Nginx 配置

  • nginx.conf
server {
      listen 80;
      listen 443 ssl;
      server_name hellowood.com.cn;
      ssl_certificate /etc/nginx/certs/hellowood.com.cn_bundle.crt;
      ssl_certificate_key /etc/nginx/certs/hellowood.com.cn.key;
      location / {
        proxy_pass http://tomcat:8080;
      }
}

http://tomcat:8080: 将所有请求都转发到 tomcat 容器的 8080端口

启动 Nginx 容器

docker pull nginx 
docker run --name nginx -d -p 80:80 -p 443:443 
  --link tomcat:tomcat 
  -v /home/ubuntu/hellowood/dev/nginx/conf:/etc/nginx/conf.d  
  -v /home/ubuntu/hellowood/dev/nginx/log:/var/log/nginx  
  -v /home/ubuntu/hellowood/dev/nginx/certs:/etc/nginx/certs nginx

此时,访问相应的域名:http://hellowood.com.cn和https://hellowood.com.cn会显示Tomcat 的首页,配置完成