解决办法
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Cpnnection "upgrade";
解决办法
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Cpnnection "upgrade";
最近,原文作者一直在使用Docker容器来开发PHP微服务套件。一个问题是PHP应用已经搭建,可以和PHP-FPM和Nginx(取代了简单的Apche/PHP环境)一起工作,因此每个PHP微服务需要两个容器(以及两个Docker镜像):一个PHP-FPM容器和一个NGinx容器。
这个应用运行了6个以上的服务,如果做个乘法,在开发和生产之间会有约30个容器。作者决定构建一个单独的NGinx Docker镜像,它可以使用PHP-FPM的主机名作为环境变量并运行单独的配置文件,而没有为每个容器构建单独的NGinx镜像。
在本文中,原文作者简要说明从上图中的方法1到方法2的转换,最后采用的方案中采用了一种新的定制Docker镜像。该镜像的代码是开源的,如果读者碰到类似问题,可以随时签出该部分代码。
NGinx和PHP-FPM配合使用能使PHP应用的性能更好,但不好的是和PHP Apache镜像不同,PHP-FPM Docker镜像缺省并没有和NGinx进行绑定。如果需要通过NGinx容器和PHP-FPM连接,需要在NGind配置里为该后端增加DNS记录。比如,如果名为php-fpm-api的PHP-FPM容器正在运行,NGinx配置文件应该包含下面部分:
location ~ .php$ {
fastcgi_split_path_info ^(.+.php)(/.+)$;
# This line passes requests through to the PHP-FPM container
fastcgi_pass php-fpm-api:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
如果只服务于单独的NGinx容器,NGinx配置中容器名字写死还可以接受,但如上所述,需要允许多个NGinx容器,每个对应于一个PHP服务。创建一个新的NGinx镜像(以后需要进行维护和升级)会有些痛苦,即使管理一批不同的数据卷,仅仅改变变量名看起来也有很多工作。
最初,作者认为这会很简单。Docker文档中有少许的几个章节讨论如何使用envsubst来完成该工作,但不幸的是,在其NGinx配置文件中,这种方法不奏效。
vhosts.conf
server {
listen 80;
index index.php index.html;
root /var/www/public;
client_max_body_size 32M;
location / {
try_files $uri /index.php?$args;
}
location ~ .php$ {
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_pass ${NGINX_HOST}:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
该vhosts.conf文件使用了NGinx内置变量,因此当依照文档运行Docker命令(/bin/bash -c “envsubst < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g ‘daemon off;’”)时,得到错误提示$uri和$fastcgi_script_name没有定义。这些变量通常通过NGinx传入,因此不能简单的识别出他们是什么并传给自身,而且这使容器的动态性变差。
接下来,作者开始研究不同的NGinx镜像。找到的两个,但它们都在随后的几年中都没有任何更新。作者开始使用martin/nginx,试图找到可以工作的原型。
Martin镜像和其它镜像有点不一样,因为它要求特定的文件夹结构。在root下增加Dockerfile:
FROM martin/nginx
接下来,我添加了一个app/空目录和conf/目录,conf/目录下只有一个文件vhosts.conf:
server {
listen 80;
index index.php index.html;
root /var/www/public;
client_max_body_size 32M;
location / {
try_files $uri /index.php?$args;
}
location ~ .php$ {
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_pass $ENV{"NGINX_HOST"}:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
这个文件和之前的配置文件几乎一样,除了有一行的改动:
fastcgi_pass $ENV{“NGINX_HOST”}:9000;。现在想要启动带命名为php-fpm-api的PHP容器的NGinx容器,就可以构建一个新的镜像,让它在以下环境变量下运行:
docker build -t shiphp/nginx-env:test .
docker run -it --rm -e NGINX_HOST=php-fpm-api shiphp/nginx-env:test
它可以正常工作了。但是,这种方法有两个困扰的地方:
1. 正在使用的基础镜像已经有两年了。这会引入安全和性能风险。
2. 有个空的/app目录看起来并不必需,因为文件会被存储在一个不同的目录中。
作者认为作为定制解决方案,从Martin镜像开始比较好,因此给项目建了分叉,创建了新的NGinx基础镜像并修复了上述两个问题。现在,如果要在NGinx容器中允许动态命名的后端,可以参照:
# 从Docker Hub得到最新版本
docker pull shiphp/nginx-env:latest
# 运行名为"php-fpm-api"的PHP容器
docker run --name php-fpm-api -v $(pwd):/var/www php:fpm
# 允许链接到PHP-FPM容器的NGinx容器
docker run --link php-fpm-api -e NGINX_HOST=php-fpm-api shiphp/nginx-env
如果想增加自己的文件或NGinx配置文件,来定制镜像,用Dockerfile来扩展它就可以:
FROM shiphp/nginx-env
ONBUILD ADD <PATH_TO_YOUR_CONFIGS> /etc/nginx/conf.d/
...
现在所有的PHP-FPM容器都使用了它们自己的Docker镜像实例,这样在升级NGinx,改变权限或做某些调整时,就变得非常轻松了。 所有的代码都在Github上,如果读者看到任何问题或有改进建议,可以直接创建一个问题单。如果有疑问或任何Docker相关的,可以在Twitter上找到我继续探讨。
查看英文原文:https://www.shiphp.com/blog/2018/nginx-php-fpm-with-env
客户端 < = > 服务器(nginx) < = > uWSGI < = > Python(Flask) < = > 数据库
源码安装、apt-get install …
sudo /usr/local/nginx/sbin/nginx -s reload
1.在nginx的主配置文件最后一个大括号的上面添加:
include vhost/*.conf;
2.在conf/下新建文件夹,用于保存所有的虚拟主机配置文件
mkdir vhost
3.vhost目录下新建一个虚拟主机的配置文件(sudo vim idandan.vip.conf)
server{
listen 80;
server_name idandan.vip;
location / {
root html/blog;
index index.html;
}
}
# sudo vim idandan.vip.conf
4.在html目录下创建blog文件夹,在blog下新建index.html
Hello World
5.重启nginx(sudo /usr/local/nginx/sbin/nginx -s reload)
6.添加本地的域名解析,修改文件:(C:WindowsSystem32driversetchosts)
最后一行添加:139.196.81.238 idandan.vip
7.测试,在浏览器地址栏输入:idandan.vip
1.安装:pip3 install uwsgi
2.配置:
http: # 采用http协议
socket: # 采用socket协议
wsgi-file # 将数据交给哪个模块
callable # 具体可调用的对象
chdir # 指定uwsgi启动后的当前目录
daemonize # 后台运行,需要指定一个日志文件
# blog.py文件
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hi'
if __name__ == '__main__':
app.run()
3.简单实例
1.在blog目录下创建blog.py文件,里面写上flask启动代码用于测试
2.启动:
sudo uwsgi --http host:port --wsgi-file blog.py --callable app
4.socket方式启动
1)nginx转发请求:
python
server{
listen 80;
server_name idandan.vip;
location / {
# root html/blog;
# index index.html;
include uwsgi_params;
uwsgi_pass 127.0.0.1:5000;
}
}
2)以socket方式启动
sudo uwsgi --socket 127.0.0.1:5000 --wsgi-file blog.py --callable app
3)将启动参数配置写进配置文件
[uwsgi]
socket = 127.0.0.1:5000
wsgi-file = blog.py
callable = app
(blog/vim uwsgi.ini)
启动:sudo uwsgi wsgi.ini
1.准备静态资源
python
1.在项目根目录下(blog)创建static目录
2.将图片拷贝到static下
2.配置nginx转发
# 添加一个location
location /static{
# root html/blog;
# 或
alias html/blog/static; # 两种方式都可以
}
开学之初,我发现Azure上有一个100刀的学生优惠。但在领取这个优惠之后,我却一直没有使用的机会,一是自己不会用,二是没有多余的时间。现在等来了放假,终于可以好好搞一搞了。:joy:
这次搭博客可谓是踩了不少坑:
1、进入Azure的门户,添加一个Ubuntu的主机,学生优惠的主机为B1S,我使用的是公钥登陆,生成公钥的过程就不说了
2、在网络安全组的入站规则中添加443和80端口
3、接下来是连接主机。可以使用PuTTY或者是MobaXterm,输入ip和用户名,再加上私钥就可以连接了。
4、安装Nginx
sudo apt-get update
sudo apt-get install nginx
安装完成后可以用以下命令操作nginx
sudo systemctl stop nginx.service
sudo systemctl start nginx.service
sudo systemctl enable nginx.service
打开网页看看是否有这样的页面出现,如果有的话就可以进行下一步操作了
5、安装MariaDB
sudo apt-get install mariadb-server mariadb-client
对于Ubuntu 16.04有以下命令
sudo systemctl stop mysql.service
sudo systemctl start mysql.service
sudo systemctl enable mysql.service
输入
sudo mysql_secure_installation
然后进行以下操作
Enter current password for root (enter for none): Just press the Enter
Set root password? [Y/n]: Y
New password: Enter password
Re-enter new password: Repeat password
Remove anonymous users? [Y/n]: Y
Disallow root login remotely? [Y/n]: Y
Remove test database and access to it? [Y/n]: Y
Reload privilege tables now? [Y/n]: Y
测试以下密码是否能登陆
sudo mysql -u root -p
6、安装PHP7.2 / PHP-FPM
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:ondrej/php
sudo apt update
sudo apt install php7.2-fpm php7.2-common php7.2-mbstring php7.2-xmlrpc php7.2-soap php7.2-gd php7.2-xml php7.2-intl php7.2-mysql php7.2-cli php7.2-zip php7.2-curl
7、重启nginx和php
sudo systemctl restart nginx.service
sudo systemctl restart php7.2-fpm.service
8、创建WordPress的数据库
sudo mysql -u root -p
CREATE DATABASE yourDBname;
CREATE USER 'yourDBusername'@'localhost' IDENTIFIED BY 'new_password_here';
GRANT ALL ON yourDBname.* TO 'yourDBusername'@'localhost' IDENTIFIED BY 'user_password_here' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EXIT;
9、安装wordpress
cd /tmp && wget https://wordpress.org/latest.tar.gz
tar -zxvf latest.tar.gz
sudo mv wordpress /var/www/html/wordpress
sudo chown -R www-data:www-data /var/www/html/wordpress/
sudo chmod -R 755 /var/www/html/wordpress/
10、配置http服务
我用的是vim
sudo vim /etc/nginx/sites-available/wordpress
找到这个东西的位置, 将example.com 换为自己的网址
server {
listen 80;
listen [::]:80;
root /var/www/html/wordpress;
index index.php index.html index.htm;
server_name example.com www.example.com;
client_max_body_size 100M;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ .php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
PHPCopy
11、开启网站
sudo ln -s /etc/nginx/sites-available/wordpress /etc/nginx/sites-enabled/
12、对网站进行配置
1)先是将示例配置文件复制一份
sudo mv /var/www/html/wordpress/wp-config-sample.php /var/www/html/wordpress/wp-config.php
2)获取secure key,打开下面的网站。
https://api.wordpress.org/secret-key/1.1/salt/
3)再进行配置
sudo vim /var/www/html/wordpress/wp-config.php
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'yourDBname');
/** MySQL database username */
define('DB_USER', 'yourDBusername');
/** MySQL database password */
define('DB_PASSWORD', 'user_password_here');
/** MySQL hostname */
define('DB_HOST', 'localhost');
/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8');
/** The Database Collate type. Don't change this if in doubt. */
define('DB_COLLATE', '');
PHPCopy
4)再找到secure key的相应位置,将自己获取到的key放进去
不要直接复制!!!
define('AUTH_KEY', 'zP}sLq>K[Q}6+-QS !Fc,wBD%373RYo.C<c=%lnE.!xY:kloSyJ@qIQ`2iVy{Sd[');
define('SECURE_AUTH_KEY', 'Zrw|4{)0]tE}bcHa8@nwM]SC:17b}-IDd)Z%1d}a}cMqI}h@|Kf>oLRL`pXdySLN');
define('LOGGED_IN_KEY', ',Nl,:NNP+R)%Y$gjpOI8~X?<;?}eTvaI4;l?T@S}V]BwsNT{*e!y.YB^#X=QI@qx');
define('NONCE_KEY', 'n2Z2|H>r|-C-y(yzG*-1btopL;N|);8lZQvIP( Dhy}xtc2vs#(2#ec,C%])Bf~[');
define('AUTH_SALT', '>`nL:waCX!k~-(9!A2.?PJpKd&,D[r}w(i;~Ck^q1M`YCWF2.fTR%;V7_+}QI76 ');
define('SECURE_AUTH_SALT', 'nshMJqJv2Z_EVt|Wtw?qJCI6N&>^{L-.ig(]Pc.3M!*,sR8i[WZg.5pQP1-t8a$z');
define('LOGGED_IN_SALT', '-nDGM,|-PWtNy02}0r^,rsJlC5#si%W{@6W]<<#PR}T)9Izv7Rc[]HKk`yk)1v38');
define('NONCE_SALT', 'QzZF]GjCkgNC;,m&jc=~gX-gWo^oUj{W]N+s5-kG?Fq?KQ^ESNhI<+xa-m+;e|?(');
13、配置ssl
1)安装 Let’s Encrypt Client
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx
2)获取免费的ssl证书
将example.com 全部更换为自己的域名
sudo certbot --nginx -m [email protected] -d example.com -d www.example.com
3)接下来的东西按照步骤走
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v01.api.letsencrypt.org/directory
-------------------------------------------------------------------------------
(A)gree/(C)ancel: A
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about EFF and
our work to encrypt the web, protect its users and defend digital rights.
-------------------------------------------------------------------------------
(Y)es/(N)o: Y
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
-------------------------------------------------------------------------------
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
最后一个一定要选择2
4)重新对配置文件进行配置
sudo nano /etc/nginx/sites-available/wordpress
server {
listen 80;
listen [::]:80;
root /var/www/html/wordpress;
index index.php index.html index.htm;
server_name example.com www.example.com;
client_max_body_size 100M;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ .php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
if ($scheme != "https") {
return 301 https://$host$request_uri;
} # managed by Certbot
# Redirect non-https traffic to https
# if ($scheme != "https") {
# return 301 https://$host$request_uri;
# } # managed by Certbot
}
直接打开你的网址,看看是否出现这个页面,出现了就说明成功啦
本篇文章记录通过Ansible自动化部署nginx的负载均衡高可用,前端代理使用nginx+keepalived,后端web server使用3台nginx用于负载效果的体现,结构图如下:
主机规划
#!/bin/bash
keypath=/root/.ssh
[ -d ${keypath} ] || mkdir -p ${keypath}
rpm -q expect &> /dev/null || yum install expect -y
ssh-keygen -t rsa -f /root/.ssh/id_rsa -P ""
password=centos
while read ip;do
expect <<EOF
set timeout 5
spawn ssh-copy-id $ip
expect {
"yes/no" { send "yesn";exp_continue }
"password" { send "$passwordn" }
}
expect eof
EOF
done < /home/iplist.txt
iplist.txt
192.168.214.148
192.168.214.143
192.168.214.133
192.168.214.135
192.168.214.139
192.168.214.134
执行脚本
[root@Ansible script]# ./autokey.sh
测试验证
[root@Ansible script]# ssh 192.168.214.148 'date'
Address 192.168.214.148 maps to localhost, but this does not map back to the address - POSSIBLE BREAK-IN ATTEMPT!
Sat Jul 14 11:35:21 CST 2018
配置Ansible基于主机名认证,方便单独管理远程主机
vim /etc/hosts
#
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.214.148 node-1
192.168.214.143 node-2
192.168.214.133 web-1
192.168.214.135 web-2
192.168.214.139 web-3
#安装ansible
[root@Ansible ~]# yum install ansible -y
#配置ansible主机清单
[root@Ansible ~]# vim /etc/ansible/hosts
[all]
192.168.214.148
192.168.214.143
192.168.214.133
192.168.214.135
192.168.214.139
[node]
192.168.214.148
192.168.214.143
[web]
192.168.214.133
192.168.214.135
192.168.214.139
#Ansible执行ping测试
[root@Ansible ~]# ansible all -m ping
先看一下web的目录结构
[root@Ansible ~]# tree /opt/roles/web
/opt/roles/web
.
├── tasks
│ ├── install_nginx.yml
│ ├── main.yml
│ ├── start.yml
│ ├── temps.yml
│ └── user.yml
└── templates
├── index.html.j2
└── nginx.conf.j2
2 directories, 7 files
按照角色执行的顺序编写
编写user.yml
- name: create group nginx
group: name=nginx
- name: create user nginx
user: name=nginx group=nginx system=yes shell=/sbin/nologin
编写install_nginx.yml
- name: install nginx webserver
yum: name=nginx
创建nginx配置文件的template模板
由于是测试,后端web服务的nginx.conf配置文件基本保持默认,只只更具后端主机情况设置worker进程数,使用ansible的setup模块中的变量获取远程主机的cpu的数量值
#将配置文件转换成template文件
[root@Ansible conf]# cp nginx.conf /opt/roles/web/templates/nginx.conf.j2
#做出修改的内容如下
worker_processes {{ansible_proccessor_vcpus}};
#在templates目录写一个测试页内如下
vim index.html.j2
{{ ansible_hostname }} test page.
编写temps.yml
- name: cp nginx.conf.j2 to nginx web server rename nginx.conf
template: src=/opt/roles/web/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: cp index test page to nginx server
template: src=/opt/roles/web/templates/index.html.j2 dest=/usr/share/nginx/html/index.html
编写start.yml
- name: restart nginx
service: name=nginx state=started
编写main.yml
- import_tasks: user.yml
- import_tasks: install_nginx.yml
- import_tasks: temps.yml
- import_tasks: start.yml
编写执行主文件web_install.yml,执行文件不能与web角色放在同一目录,通常放在roles目录
[root@Ansible ~]# vim /opt/roles/web_install.yml
---
- hosts: web
remote_user: root
roles:
- web
安装前测试: -C选项为测试
[root@Ansible ~]# ansible-playbook -C /opt/roles/web_install.yml
如没有问题则执行安装
[root@Ansible ~]# ansible-playbook /opt/roles/web_install.yml
测试访问
[root@Ansible ~]# ansible web -m shell -a 'iptables -F'
192.168.214.139 | SUCCESS | rc=0 >>
192.168.214.135 | SUCCESS | rc=0 >>
192.168.214.133 | SUCCESS | rc=0 >>
[root@Ansible ~]# curl 192.168.214.133
web-1 test page.
部署高可用集群需要注意各节点包括后端主机的时间问题,保证各主机时间一致。
[root@Ansible ~]# ansible all -m shell -a 'yum install ntpdate -y'
[root@Ansible ~]# ansible all -m shell -a 'ntpdate gudaoyufu.com'
编写user.yml
- name: create nginx group
group: name=nginx
- name: create nginx user
user: name=nginx group=nginx system=yes shell=/sbin/nologin
编写install_server.yml
- name: install nginx and keepalived
yum: name={{ item }} state=latest
with_items:
- nginx
- keepalived
编写temps.yml
- name: copy nginx proxy conf and rename
template: src=/opt/roles/ha_proxy/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: copy master_keepalived.conf.j2 to MASTER node
when: ansible_hostname == "node-1"
template: src=/opt/roles/ha_proxy/templates/master_keepalived.conf.j2 dest=/etc/keepalived/keepalived.conf
- name: copy backup_keepalived.conf.j2 to BACKUP node
when: ansible_hostname == "node-2"
template: src=/opt/roles/ha_proxy/templates/backup_keepalived.conf.j2 dest=/etc/keepalived/keepalived.conf
配置nginx proxy配置文件模板
[root@Ansible ~]# cp /opt/conf/nginx.conf /opt/roles/ngx_proxy/templates/nginx.conf.j2
[root@Ansible ~]# vim /opt/roles/ngx_proxy/templates/nginx.conf.j2
user nginx;
worker_processes {{ ansible_processor_vcpus }};
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
# Load dynamic modules. See /usr/share/nginx/README.dynamic.
events {
worker_connections 1024;
}
http {
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 /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
upstream web {
server 192.168.214.133:80 max_fails=3 fail_timeout=30s;
server 192.168.214.135:80 max_fails=3 fail_timeout=30s;
server 192.168.214.139:80 max_fails=3 fail_timeout=30s;
}
server {
listen 80 default_server;
server_name {{ ansible_hostname }};
root /usr/share/nginx/html;
index index.html index.php;
location / {
proxy_pass http://web;
}
error_page 404 /404.html;
}
}
配置keepalived配置文件模板
[root@Ansible ~]# cp /opt/conf/keepalived.conf /opt/roles/ha_proxy/templates/master_keepalived.conf.j2
[root@Ansible templates]# vim master_keepalived.conf.j2
#
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
[email protected]
[email protected]
}
notification_email_from [email protected]
smtp_server 192.168.214.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
vrrp_iptables
vrrp_mcast_group4 224.17.17.17
}
vrrp_script chk_nginx {
script "killall -0 nginx"
interval 1
weight -20
fall 2
rise 1
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 55
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 12345678
}
virtual_ipaddress {
192.168.214.100
}
track_script {
chk_nginx
}
}
同样,在master_keepalived.conf.j2基础修改另存为backup_keepalived.conf.j2,只修改角色与优先级即可。注意:master_keepalived.conf.j2文件中的检测故障降低优先级的值要确保降低后MASTER优先级小于BACKUP的优先级
编写start.yml
- name: start nginx proxy server
service: name=nginx state=started
编写main.yml
- import_tasks: user.yml
- import_tasks: install_server.yml
- import_tasks: temps.yml
- import_tasks: start.yml
编写执行主文件
[root@Ansible ~]# vim /opt/roles/ha_proxy_install.yml
---
- hosts: node
remote_user: root
roles:
- ha_proxy
执行检测roles
[root@Ansible ~]# ansible-playbook -C /opt/roles/ha_proxy_install.yml
执行测试没问题即可执行自动部署
执行过程如下:
[root@Ansible ~]# ansible-playbook /opt/roles/ha_proxy_install.yml
PLAY [node] **********************************************************************************************************************
TASK [Gathering Facts] ***********************************************************************************************************
ok: [192.168.214.148]
ok: [192.168.214.143]
TASK [ha_proxy : create nginx group] *********************************************************************************************
changed: [192.168.214.148]
ok: [192.168.214.143]
TASK [ha_proxy : create nginx user] **********************************************************************************************
changed: [192.168.214.148]
ok: [192.168.214.143]
TASK [ha_proxy : install nginx and keepalived] ***********************************************************************************
changed: [192.168.214.143] => (item=[u'nginx', u'keepalived'])
changed: [192.168.214.148] => (item=[u'nginx', u'keepalived'])
TASK [ha_proxy : copy nginx proxy conf and rename] *******************************************************************************
changed: [192.168.214.148]
changed: [192.168.214.143]
TASK [ha_proxy : copy master_keepalived.conf.j2 to MASTER node] ******************************************************************
skipping: [192.168.214.143]
changed: [192.168.214.148]
TASK [ha_proxy : copy backup_keepalived.conf.j2 to BACKUP node] ******************************************************************
skipping: [192.168.214.148]
changed: [192.168.214.143]
TASK [ha_proxy : start nginx proxy server] ***************************************************************************************
changed: [192.168.214.143]
changed: [192.168.214.148]
PLAY RECAP ***********************************************************************************************************************
192.168.214.143 : ok=7 changed=4 unreachable=0 failed=0
192.168.214.148 : ok=7 changed=6 unreachable=0 failed=0
至此,自动部署nginx+keepalived高可用负载均衡完成了
最后看一下roles目录的结构
[root@Ansible ~]# tree /opt/roles/
/opt/roles/
├── ha_proxy
│ ├── tasks
│ │ ├── install_server.yml
│ │ ├── main.yml
│ │ ├── start.yml
│ │ ├── temps.yml
│ │ └── user.yml
│ └── templates
│ ├── backup_keepalived.conf.j2
│ ├── master_keepalived.conf.j2
│ └── nginx.conf.j2
├── ha_proxy_install.retry
├── ha_proxy_install.yml
├── web
│ ├── tasks
│ │ ├── install_nginx.yml
│ │ ├── main.yml
│ │ ├── start.yml
│ │ ├── temps.yml
│ │ └── user.yml
│ └── templates
│ ├── index.html.j2
│ └── nginx.conf.j2
├── web_install.retry
└── web_install.yml
6 directories, 19 files
下面测试服务:keepalived的服务没有在ansible中设置自动启动,到keepalived节点启动即可。
测试node节点
[root@Ansible ~]# for i in {1..10};do curl 192.168.214.148;done
web-3 test page.
web-1 test page.
web-2 test page.
web-3 test page.
web-1 test page.
web-2 test page.
web-3 test page.
web-1 test page.
web-2 test page.
web-3 test page.
将node-1 的MASTER服务停掉测试故障转移,同时查看node-2状态变化
执行: nginx -s stop
查看vrrp通知,可以看到主备切换正常:
[root@node-2 ~]# tcpdump -i ens33 -nn host 224.17.17.17
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
16:55:20.804327 IP 192.168.214.148 > 224.17.17.17: VRRPv2, Advertisement, vrid 55, prio 100, authtype simple, intvl 1s, length 20
16:55:25.476397 IP 192.168.214.148 > 224.17.17.17: VRRPv2, Advertisement, vrid 55, prio 0, authtype simple, intvl 1s, length 20
16:55:26.128474 IP 192.168.214.143 > 224.17.17.17: VRRPv2, Advertisement, vrid 55, prio 90, authtype simple, intvl 1s, length 20
16:55:27.133349 IP 192.168.214.143 > 224.17.17.17: VRRPv2, Advertisement, vrid 55, prio 90, authtype simple, intvl 1s, length 20
再测试访问:
[root@Ansible ~]# for i in {1..10};do curl 192.168.214.148;done
web-1 test page.
web-2 test page.
web-3 test page.
web-1 test page.
web-2 test page.
web-3 test page.
web-1 test page.
web-2 test page.
web-3 test page.
web-1 test page.
node-1恢复主节点,抢回MASTER角色
node-1节点执行nginx指令,可以看到VIP漂移回到node-1节点,测试访问
[root@Ansible ~]# for i in {1..10};do curl 192.168.214.148;done
web-1 test page.
web-2 test page.
web-3 test page.
web-1 test page.
web-2 test page.
web-3 test page.
web-1 test page.
web-2 test page.
web-3 test page.
web-1 test page.
上面的自动部署方式还有可以改进的地方,比如,可以将配置keepalived的配置文件中的许多参数在roles中以统一变量的方式定义,然后在template模板文件中引用参数就可以了
此外还有一个需要注意的地方是:keepalived的配置文件中使用了killall指令检测本地的nginx服务状态,如果检测结果状态为非0就会执行vrrp_script中定义的降级操作,要确保系统这个指令可以执行,有时该指令没有被安装,如果该指令没有存在,即使MASTER节点发生故障也不会发生变化。
Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。在Java的Web架构中,通常使用Tomcat和Nginx进行配合,Nginx作为反向代理服务器,可以对后台的Tomcat服务器负载均衡,也可以让Nginx处理静态页面的请求、Tomcat处理JSP页面请求达到动静分离的目的。
系统环境:
软件包百度下载: https://pan.baidu.com/share/init?surl=3fbIn0EuEcSVplRk4tRnAg&third=15 密码:6b7e
网站拓扑架构图:
开始部署
1.安装jdk并设置java环境
#安装jdk软件包
rpm -ivh jdk-10.0.1_linux-x64_bin.rpm
#添加jdk的环境变量,新建java.sh并写入以下内容
vim /etc/profile.d/java.sh
export JAVA_HOME=/usr/java/jdk-10.0.1
export PATH=$JAVA_HOME/bin:$PATH
#加载环境变量
source /etc/profile.d/java.sh
2.查看jdk版本信息
java -version
如下图表示jdk已经安装成功了
3.解压并安装tomcat
#解压缩软件包
tar zxvf apache-tomcat-8.5.11.tar.gz
#移动tomcat目录
mv apache-tomcat-8.5.11 /usr/local/tomcat8
4.启动tomcat服务
#启动服务
/usr/local/tomcat8/bin/startup.sh
netstat -tunlp | grep 8080
6.创建站点目录
mkdir -p /web/webapp
7.为站点新建首页文件index.jsp
vim /web/webapp/index.jsp
#以为下index.jsp内容
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<html>
<head>
<title>hello</title>
</head>
<body>
<% out.println("<h1>This is tomcat 1 web.</h1>"); %>
</body>
</html>
8.编辑tomcat主配置文件,以支持新站点:
vim /usr/local/tomcat8/conf/server.xml
#在<Host>标签内,新增第二行记录
<Context docBase="/web/webapp" path="" reloadable="false"></Context>
9.重启tomcat服务
#关闭服务
/usr/local/tomcat8/bin/shutdown.sh
#开启服务
/usr/local/tomcat8/bin/startup.sh
#关闭安全设置
setenforce 0
#关闭防火墙
systemctl stop firewalld.service
Tomcat服务器1 和 Tomcat服务器2 安装及配置等一样,只是测试网页内容有差异,具体网页内容显示如下图
Tomcat服务器1:
Tomcat服务器2:
1.安装依赖包(需要连接网络或者通过系统镜像ISO文件安装)
yum -y install pcre-devel zlib-devel gcc gcc-c++ make
2.创建管理用户nginx
useradd -M -s /sbin/nologin nginx
3.解压nginx,并进入解压后nginx目录
tar xzvf nginx-1.6.0.tar.gz -C /opt
cd /opt/nginx-1.6.0/
4.配置
./configure
--prefix=/usr/local/nginx
--user=nginx
--group=nginx
--with-http_stub_status_module //开启stub_status状态统计模块//
5.编译及安装
make && make install
6.nginx连接至系统命令区,方便命令使用
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
7.创建nginx管理脚本
vi /etc/init.d/nginx
#!/bin/bash
#chkconfig: - 99 20
#description: Nginx Service Control Script
PROG="/usr/local/nginx/sbin/nginx"
PIDF="/usr/local/nginx/logs/nginx.pid"
case "$1" in
start)
$PROG
;;
stop)
kill -s QUIT $(cat $PIDF)
;;
restart)
$0 stop
$0 start
;;
reload)
kill -s HUP $(cat $PIDF)
;;
*)
echo "Usage: $0 {start|stop|restart|reload}"
exit 1
esac
exit 0
8.为nginx赋予执行权限,并加入系统服务管理
chmod +x /etc/init.d/nginx
chkconfig --add nginx
vim /usr/local/nginx/conf/nginx.conf
#http{}标签内添加以下命令
upstream tomcat_server {
server 192.168.100.6:8080 weight=1;
server 192.168.100.7:8080 weight=1;
}
#在location / {}标签内添加
location / {
root html;
index index.html index.htm;
proxy_pass http://tomcat_server; #通过proxy_pass方法进行代理至tomcat_server的服务器组,其中http://不能省略
}
2.检查nginx配置
nginx -t
3.重启nginx服务
killall -1 nginx
#关闭selinux
setenforce 0
#关闭防火墙
systemctl stop firewalld.service
测试
客户机访问Nginx服务器IP地址:http://192.168.100.25/,通过不断的刷新浏览器测试,可以看到哦由于权重相同,页面在两个tomcat站点反复切换,这样说明负载均衡集群搭建成功了。
指定服务安装的通用位置
mkdir /usr/local/services
SERVICE_PATH=/usr/local/services
创建服务运行的账户
useradd -r -M -s /sbin/nologin www
安装所需依赖包
yum -y install pcre pcre-devel
gperftools gcc zlib-devel
libxml2 libxml2-devel
bzip2 bzip2-devel
curl curl-devel
libjpeg-devel libjpeg
libpng-devel libpng
freetype freetype-devel
libmcrypt libmcrypt-devel
openssl-devel
下载解压NGINX+OPENSSL
NGINX_URL="http://nginx.org/download/nginx-1.14.0.tar.gz"
OPENSSL_URL="https://www.openssl.org/source/openssl-1.1.0h.tar.gz"
wget -P ${SERVICE_PATH} ${NGINX_URL} && tar -zxvf ${SERVICE_PATH}/nginx*.tar.gz -C ${SERVICE_PATH}
wget -P ${SERVICE_PATH} ${OPENSSL_URL} && tar -zxvf ${SERVICE_PATH}/openssl*.gz -C ${SERVICE_PATH}
编译安装NGINX
cd ${SERVICE_PATH}/nginx-*;./configure
--prefix=${SERVICE_PATH}/nginx
--user=www --group=www
--with-http_stub_status_module
--with-http_ssl_module
--with-http_flv_module
--with-pcre
--with-http_gzip_static_module
--with-openssl=${SERVICE_PATH}/openssl*
--with-http_realip_module
--with-google_perftools_module
--without-select_module
--without-mail_pop3_module
--without-mail_imap_module
--without-mail_smtp_module
--without-poll_module
--without-http_autoindex_module
--without-http_geo_module
--without-http_uwsgi_module
--without-http_scgi_module
--without-http_memcached_module
--with-cc-opt='-O2' && cd ${SERVICE_PATH}/nginx-*;make && make install
NGINX+OPENSSL安装完成后的清理与其他配置
ln -sv ${SERVICE_PATH}/nginx /usr/local/
rm -rf ${SERVICE_PATH}/nginx/conf/*.default
cd ${SERVICE_PATH} ; rm -rf nginx*.tar.gz openssl*.tar.gz
写入主配置文件nginx.conf(配置已优化)
cat << EOF >/usr/local/nginx/conf/nginx.conf
user www;
worker_processes WORKERNUMBER;
worker_cpu_affinity auto;
worker_rlimit_nofile 655350;
error_log /var/log/nginx_error.log;
pid /tmp/nginx.pid;
google_perftools_profiles /tmp/tcmalloc;
events {
use epoll;
worker_connections 655350;
multi_accept on;
}
http {
charset utf-8;
include mime.types;
default_type text/html;
log_format main '"$remote_addr" - [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" '
'"$sent_http_server_name $upstream_response_time" '
'$request_time '
'$args';
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 120;
client_body_buffer_size 512k;
client_header_buffer_size 64k;
large_client_header_buffers 4 32k;
client_max_body_size 300M;
client_header_timeout 15s;
client_body_timeout 50s;
open_file_cache max=102400 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 1;
server_names_hash_max_size 2048;
server_names_hash_bucket_size 256;
server_tokens off;
gzip on;
gzip_proxied any;
gzip_min_length 1024;
gzip_buffers 4 8k;
gzip_comp_level 9;
gzip_disable "MSIE [1-6].";
gzip_types application/json test/html text/plain text/css application/font-woff application/pdf application/octet-stream application/x-javascript application/javascript application/xml text/javascript;
fastcgi_cache_path /dev/shm/ levels=1:2 keys_zone=fastcgicache:512m inactive=10m max_size=3g;
fastcgi_cache_lock on;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
fastcgi_send_timeout 300;
fastcgi_connect_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 256k;
fastcgi_buffers 4 128k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
include vhost/*.conf;
}
EOF
NGINX worker进程数配置,指定为逻辑CPU数量的2倍
THREAD=`expr $(grep process /proc/cpuinfo |wc -l) * 2`
sed -i s"/WORKERNUMBER/$THREAD/" ${SERVICE_PATH}/nginx/conf/nginx.conf
下载并解压PHP-FPM软件
FPM_URL="http://mirrors.sohu.com/php/php-5.6.8.tar.gz"
wget -P ${SERVICE_PATH} ${FPM_URL} && tar -zxvf ${SERVICE_PATH}/php*.tar.gz -C ${SERVICE_PATH}
编译安装PHP-FPM
cd ${SERVICE_PATH}/php-*;./configure
--prefix=${SERVICE_PATH}/php
--with-gd
--with-mcrypt
--with-mysql=mysqlnd
--with-mysqli=mysqlnd
--with-pdo-mysql=mysqlnd
--enable-maintainer-zts
--enable-ftp
--enable-zip
--with-bz2
-with-iconv-dir
--with-freetype-dir
--with-jpeg-dir
--with-png-dir
--with-config-file-path=${SERVICE_PATH}/php
--enable-mbstring
--enable-fpm
--with-fpm-user=www
--with-fpm-group=www
--disable-debug
--enable-opcache
--enable-soap
--with-zlib
--with-libxml-dir=/usr
--enable-xml
--disable-rpath
--enable-bcmath
--enable-shmop
--enable-sysvsem
--enable-inline-optimization
--with-curl
--enable-mbregex
--enable-gd-native-ttf
--with-openssl
--with-mhash
--enable-pcntl
--enable-sockets
--with-xmlrpc
--with-pear
--with-gettext
--disable-fileinfo && cd ${SERVICE_PATH}/php-*;make && make install
若FPM程序有插件需求,如mongo或redis连接插件,则可通过pecl安装php相关插件
${SERVICE_PATH}/php/bin/pecl install mongo || exit
${SERVICE_PATH}/php/bin/pecl install redis || exit
安装完成后的配置清理
ln -sv ${SERVICE_PATH}/php /usr/local/
php.ini配置文件写入(配置已优化)
cat << EOF >${SERVICE_PATH}/php/php.ini
[PHP]
engine = On
short_open_tag = Off
asp_tags = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = 17
disable_functions = shell_exec,phpinfo,exec
disable_classes =
zend.enable_gc = On
expose_php = Off
max_execution_time = 60
max_input_time = 60
memory_limit = 128M
error_reporting = E_WARING & ERROR
display_errors = Off
display_startup_errors = Off
log_errors = On
log_errors_max_len = 2048
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
track_errors = Off
html_errors = Off
error_log = /var/log/php_errors.log
variables_order = "GPCS"
request_order = "GP"
register_argc_argv = Off
auto_globals_jit = On
post_max_size = 8M
auto_prepend_file =
auto_append_file =
default_mimetype = "text/html"
default_charset = "UTF-8"
doc_root =
user_dir =
enable_dl = Off
cgi.fix_pathinfo=0
file_uploads = On
upload_max_filesize = 2M
max_file_uploads = 20
allow_url_fopen = Off
allow_url_include = Off
default_socket_timeout = 60
[CLI Server]
cli_server.color = On
[Date]
[filter]
[iconv]
[intl]
[sqlite]
[sqlite3]
[Pcre]
[Pdo]
[Pdo_mysql]
pdo_mysql.cache_size = 2000
pdo_mysql.default_socket=
[Phar]
[mail function]
SMTP = localhost
smtp_port = 25
mail.add_x_header = On
[SQL]
sql.safe_mode = Off
[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
[Interbase]
ibase.allow_persistent = 1
ibase.max_persistent = -1
ibase.max_links = -1
ibase.timestampformat = "%Y-%m-%d %H:%M:%S"
ibase.dateformat = "%Y-%m-%d"
ibase.timeformat = "%H:%M:%S"
[MySQL]
mysql.allow_local_infile = On
mysql.allow_persistent = On
mysql.cache_size = 2000
mysql.max_persistent = -1
mysql.max_links = -1
mysql.default_port =
mysql.default_socket =
mysql.default_host =
mysql.default_user =
mysql.default_password =
mysql.connect_timeout = 60
mysql.trace_mode = Off
[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.cache_size = 2000
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = Off
[OCI8]
[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
[Sybase-CT]
sybct.allow_persistent = On
sybct.max_persistent = -1
sybct.max_links = -1
sybct.min_server_severity = 10
sybct.min_client_severity = 10
[bcmath]
bcmath.scale = 0
[browscap]
[Session]
session.save_handler = files
session.save_path = "/tmp"
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 5
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
[MSSQL]
mssql.allow_persistent = On
mssql.max_persistent = -1
mssql.max_links = -1
mssql.min_error_severity = 10
mssql.min_message_severity = 10
mssql.compatibility_mode = Off
mssql.secure_connection = Off
[Assertion]
[COM]
[mbstring]
[gd]
gd.jpeg_ignore_warning = 0
[exif]
[Tidy]
tidy.clean_output = Off
[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5
[sysvshm]
[ldap]
ldap.max_links = -1
[mcrypt]
[dba]
[opcache]
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.validate_timestamps=1
opcache.revalidate_freq=30
opcache.fast_shutdown=1
opcache.enable_file_override=1
[curl]
[openssl]
extension_dir='${SERVICE_PATH}/php/lib/php/extensions/'
;extension=mongo.so
;extension=redis.so
EOF
php-fpm.conf配置文件写入(配置已优化)
cat << EOF >${SERVICE_PATH}/php/etc/php-fpm.conf
[global]
error_log = /var/log/php-fpm-error.log
log_level = warning
process_control_timeout = 10
rlimit_files = 655350
events.mechanism = epoll
[www]
user = www
group = www
listen = /dev/shm/php-fpm.sock
listen.backlog = 2048
listen.owner = www
listen.group = www
listen.mode = 0660
pm = dynamic
pm.max_children = 200
pm.start_servers = 105
pm.min_spare_servers = 10
pm.max_spare_servers = 200
pm.process_idle_timeout = 10s;
pm.max_requests = 1000
pm.status_path = /fpmstatus
ping.path = /ping
ping.response = pong
slowlog = /var/log/php-slow-$pool.log
request_slowlog_timeout = 10
request_terminate_timeout = 0
rlimit_files = 655350
security.limit_extensions = .php
EOF
mkdir /usr/local/nginx/conf/vhost
cat << EOF > /usr/local/nginx/conf/vhost/erbiao.ex.com.conf
server
{
listen 80 backlog=1024;
server_name erbiao.ex.com;
index index.php index.html ;
root /www/web/;
access_log off;
add_header Server-Name WEBerbiaoEX;
location ~ .php {
fastcgi_pass unix:/dev/shm/php-fpm.sock;
fastcgi_index index.php;
include fastcgi.conf;
set $real_script_name $fastcgi_script_name;
if ($fastcgi_script_name ~ "^(.+?.php)(/.+)$") {
set $real_script_name $1;
set $path_info $2;
}
fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
fastcgi_param SCRIPT_NAME $real_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}
location ~ .*.(js|css)?$
{
expires 12h;
}
}
}
EOF
若在同一服务器运行nginx和php-fpm,并发量不超过1000,选择unix socket,如此可避免一些检查操作(路由等),因此更快,更轻。若是高并发业务,则选择使用更可靠的tcp socket,以负载均衡、内核优化等运维手段维持效率
启动nginx和php-fpm
/usr/local/nginx/sbin/nginx
/usr/local/php-fpm/sbin/php-fpm
命令其他选项
nginx
├── -s选项,向主进程发送信号
| ├── reload参数,重新加载配置文件
| ├── stop参数,快速停止nginx
| ├── reopen参数,重新打开日志文件
| ├── quit参数,Nginx在退出前完成已经接受的连接请求
├── -t选项,检查配置文件是否正确
├── -c选项,用于指定特定的配置文件并启动nginx
├── -V选项(大写),显示nginx编译选项与版本信息
php-fpm
├── -t选项,检查配置文件是否正确
├── -m选项,显示所有已安装模块
├── -i选项,显示PHP详细信息
├── -v选项,显示版本信息
一开始搭建的hexo博客,hexo博客有个缺点,他是用nodejs的服务器,不太稳定,服务器经常挂。所以最后还是决定用nginx+php-fpm搭建一个wordpress站点,这样网站就比较稳定。废话不多说,直接进入主题。
我是用的centos的服务器,下面的一些个命令也是centos的命令,不过其他的也相差不大,主要的是步骤正确就好。
安装nginx
使用yum安装nginx
yum install nginx -y
安装完之后修改配置文件 /etc/nginx/nginx.conf
ps:要是配置文件不在这个位置的,可以利用find命令和whereis命令进行查询,参考我另外两篇博文
配置文件参考下面进行更改:
这一步,只需要两处,去除对 IPv6 地址的监听,修改要监听的域名,即:
#listen [::]:80 default_server;
server_name www.***.com;
修改完了之后,就可以启动nginx,查看自己网站首页了,应该看到的是一个nginx测试页面。
启动nginx
nginx
将 Nginx 设置为开机自动启动:
chkconfig nginx on
安装php+php-fpm+php-mysql
这一步有两个选择,安装php7.0版本或是老的版本
安装老的版本比较简单:
yum install php-fpm php-mysql -y
要是想安装php7.0版本,要先添加源,再安装:
如果是centos6,那么执行以下命令
CentOS/RHEL 6.x:
rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm
rpm -Uvh https://mirror.webtatic.com/yum/el6/latest.rpm
如果是centos7.x,那么执行以下命令
CentOS/RHEL 7.x:
rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
安装php和插件:
可以像上面一样,需要哪个装哪个,也可以全部安装
全部安装:
yum install php70w php70w*
安装需要的:
yum install php70w-common php70w-fpm php70w-opcache php70w-gd php70w-mysqlnd php70w-mbstring php70w-pecl-redis php70w-pecl-memcached php70w-devel
具体可以参考:帐号登录
完了之后启动php-fpm:
service php-fpm start
安装mysql
yum install mysql-server -y
行不通可参考:centos7 mysql数据库安装和配置
yum install wordpress -y
安装完成后,就可以在 /usr/share/wordpress 看到 WordPress 的源代码了。
由于上面的安装方法默认安装的是英文版,所以我们还要下载中文语言包,如果不需要中文安装可跳过此步骤
wget https://cn.wordpress.org/wordpress-4.8.1-zh_CN.tar.gz
tar -zxvf wordpress*
mv -f wordpress/wp-content/languages /usr/share/wordpress/wp-content/
rm -rf wordpress*
登录mysql,这里初次没有密码,你自己要设置一个密码
mysql -uroot
创建数据库
CREATE DATABASE wordpress;
完成退出
exit;
配置wordpress
进入wordpress目录下,根目录下有一个配置文件wp-config.php,把数据库名,用户,密码配置好就可以,数据库就是刚才建立 的数据库
define('DB_NAME', 'wordpress');
define('DB_USER', 'root');
define('DB_PASSWORD', 'MyPas$word4Word_Press');
修改这三行即可
再次配置/etc/nginx/nginx.conf文件:
完全按照下面配置,修改域名为你的域名即可
server {
listen 80 default_server;
#listen [::]:80 default_server;
server_name www.***.com;
root /usr/share/wordpress;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
index index.php index.html index.htm;
try_files $uri $uri/ /index.php index.php;
}
location ~ .php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
到这一步基本就完成了
nginx重新加载配置
nginx -s reload
访问页面进入wordpress仪表盘
修改nginx和php-fpm的用户和用户组时除了修改
nginx.conf 下的
user *****
和/etc/php-fpm.d/www.conf下的
user = ****
group = ****
修改上面之后,重启nginx和php-fpm,ps -ef|grep … 会发现应用的用户和用户组变了,但是这还能算万事大吉
还要修改一下一些目录下的权限
(以 修改的用户和用户组为nobody为例)
/var/log/nginx
, chown -R nobody:nobody /var/log/nginx
否则不能不能读写access.log
和errorlog
还有 上传文件用到的一个路径 /var/lib/nginx/tmp/
, chown -R nobody:nobody /var/lib/nginx
否则上传文件出错,因为保存不了上传的临时文件
3.还有的就是php-fpm的配置文件中
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session
设置的session保存的路径,如果你修改了php-fpm的用户和用户组,重启之后,你会发现什么登陆状态,验证码都保存不了,没错session没保存,因为没有修改上面保存session路径的权限
所以应该 让你修改的用户拥有/var/lib/php/session
的读写权限,chown
或者chmod
反正让php-fpm的应用用户有权限访问就可以了
扩展:
“ nobody就是一个普通账户,因为默认登录shell是 ‘/sbin/nologin’,所以这个用户是无法直接登录系统的,也就是黑客很难通过漏洞连接到你的服务器来做破坏。此外这个用户的权限也给配置的很低。因此有比较高的安全性。一切都只给最低权限。这就是nobody存在的意义。”
——-摘自 https://blog.csdn.net/gjkun0202/article/details/71156205
查看linux用户列表
cat /etc/passwd|grep -v nologin|grep -v halt|grep -v shutdown|awk -F":" '{ print $1"|"$3"|"$4 }'|more
查看nobody用户所在的组,以及组内成员 groups nobody
查看所有用户组 cat /etc/group
——-摘自 https://www.cnblogs.com/jackyyou/p/5498083.html
WordPress的多站点功能允许安装一个WordPress程序的情况下,实现多个站点(也就是一套程序,可以绑定多个域名或子域名)。
每个站点拥有独立的主题、插件、文章以及页面。
这样可以极大的减少了维护和更新多个WordPress安装程序的麻烦,
并且,每个站点之间又能够相互独立,互不影响。
WordPress multisite有两个方式:子目录和子域名,这里我们主要介绍子域名方式。
也就是说,在主域名的基础上,我们会创建一个子域名,例如:http://shop.awaimai.com。
同时,我们可以映射这个子域名到一个一级域名如:http://shop.com,
对于访问者来说,访问的就是独立的一级域名。
WordPress介绍其多站点功能页面:站点网络管理页面
接着,我们准备几个域名,如下:
注意:WordPress安装后请勿擅自在后台修改域名,即使是把有www改成无www,或者反过来,都有可能引起 redirected you too many times. 错误,详情请看[参考资料2]
然后,登录域名服务商的解析页面,把以上域名的A记录全部设置为WordPress安装的服务器IP。
也可以在本地电脑测试,可以直接修改hosts文件,加入下面1行:
127.0.0.1 www.awaimai.com blog.awaimai.com news.com shop.com
在Nginx配置目录下创建新建一个配置文件,如下:
$ sudo vi /etc/nginx/conf.d/awaimai.conf
内容为:
server {
listen 80;
server_name www.awaimai.com blog.awaimai.com news.com shop.com;
root /usr/share/nginx/wordpress;
index index.php;
location / {
try_files $uri $uri/ /index.php?$args ;
}
location ~ /favicon.ico {
access_log off;
log_not_found off;
}
location ~ .php$ {
try_files $uri /index.php;
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
access_log /var/log/nginx/$host-access.log;
error_log /var/log/nginx/wpms-error.log;
}
这里我们使用$host变量可以让Nginx为每个域名生成独立的访问日志,
如:news.com-access.log 和 shop.com-access.log。
但是error日志不能用$host变量,所以所有的错误会记录在一个文件里面。
再重启Nginx服务器:
$ nginx -s reload
按照WordPress正常安装步骤安装WordPress。
用文本编辑器打开 wp-config.php 文件,在注释:/* 好了!请不要再继续编辑。请保存本文件。使用愉快! */之前加上如下一行:
/* Multisite settings */
define( 'WP_ALLOW_MULTISITE', true );
接下来我们还会编辑这个文件几次。
保存后登录WordPress后台,点击:工具 > 网络设置,选择 子域名,网络标题和网络管理员邮箱任意输入。
然后端机安装。
稍等片刻后,界面出现两个代码块,提示分别加入wp-config.php和.htaccesss文件。
这里我们用的是Nginx,所以不需要管 .htaccess 部分。
打开wp-config.php文件,还是在注释:/* 好了!请不要再继续编辑。请保存本文件。使用愉快! */之前,加上如下几行:
define('MULTISITE', true);
define('SUBDOMAIN_INSTALL', true);
define('DOMAIN_CURRENT_SITE', 'www.awaimai.com');
define('PATH_CURRENT_SITE', '/');
define('SITE_ID_CURRENT_SITE', 1);
define('BLOG_ID_CURRENT_SITE', 1);
Log out of the WordPress admin panel, and log in again.
登出WordPress后台,再登入。
打开面板左上角 我的站点 > 网络管理 > 站点。
点击 添加新的 按钮,打开添加新站点表单,依次添加 blog、news、shop三个子域名。
添加完成后,选 所有站点 ,编辑 news.awaimai.com 和 shop.awaimai.com 两个子域名,站点标题分别为新闻和商城,
把 站点地址(URL)分别改成:news.com和 shop.com。
这一步完成后,我们就可以访问blog.awaimai.com了,它已经是一个独立的站点了,拥有独立的资源了。
但是要能访问news.com和shop.com,还需继续往下看。
打开面板左上角 我的站点 > 网络管理 > 插件。
在这里安装 WordPress MU Domain Mapping 插件,直接搜索或者下载安装都可以,然后启用。
接着复制插件目录(目录wp-content/plugins/wordpress-mu-domain-mapping)下的 sunrise.php 文件到 wp-content 目录。
打开wp-config.php文件,还是在注释:/* 好了!请不要再继续编辑。请保存本文件。使用愉快! */之前,加上如下一行:
define('SUNRISE', 'on');
保存,然后返回浏览器,在后台中打开面板左上角 我的站点 > 网络管理 > 设置。
再选择Domain Mapping,修改 Domain Options 为如下图:
然后保存。
这里的配置的功能是:重定向所有二级域名(如 news.awaimai.com )到各自的外部域名(如 news.com),包括管理页面(/wp-admin)。
接下来,我们要映射一级域名到各个站点ID。
默认在后台不显示站点ID,所以我们用一个最简单的方法让后台直接显示站点ID。
这个方法就是用WordPress的 Must-use plugin。
在 wp-content 目录下创建一个 mu-plugins 目录,再在新建的目录下创建一个名为 wpms_blogid.php 的文件,
这个PHP文件的内容为:
<?php
add_filter( 'wpmu_blogs_columns', 'do_get_id' );
add_action( 'manage_sites_custom_column', 'do_add_columns', 10, 2 );
add_action( 'manage_blogs_custom_column', 'do_add_columns', 10, 2 );
function do_add_columns( $column_name, $blog_id ) {
if ( 'blog_id' === $column_name )
echo $blog_id;
return $column_name;
}
function do_get_id( $columns ) {
$columns['blog_id'] = 'ID';
return $columns;
}
保存后再访问后台的 站点 > 所有站点,在站点列表中就会多一列ID,下一步就会用到。
后台控制面板切换到 设置 > Domains,加入两个域名:
以及:
如果域名是有www的,一样的操作方式。
以上步骤完成之后,基本就OK了。
主站点域名还是不变,还是www.awaimai.com。
用 news.com 就可以访问新闻站点,
用 shop.com 就可以访问商城站点,
博客还是可以用二级域名 blog.awaimai.com 访问。
同时,这几个站点的后台也有独立的地址:
http://www.awaimai.com/wp-admin/
http://blog.awaimai.com/wp-admin/
http://news.com/wp-admin/
http://shop.com/wp-admin/
以后再安装主题和插件不能在每个站点中安装了,
都统一在网络管理(面板左上角 我的站点 > 网络管理 )中进行配置。