CentOS8搭建Web服务器笔记2 Swoole4+Laravel8+LaravelS3
1. Swoole PHP 协程框架
Swoole 使 PHP 开发人员可以编写高性能高并发的 TCP、UDP、Unix Socket、HTTP、 WebSocket 等服务,让 PHP 不再局限于 Web 领域。
1.1 查询最新发布版本
https://github.com/swoole/swoole-src/releases
1.2 下载源码包
https://github.com/swoole/swoole-src/archive/v4.6.3.tar.gz
[root@VM-0-16-centos downloads]# wget -O swoole4.6.3.tar.gz https://github.com/swoole/swoole-src/archive/v4.6.3.tar.gz
[root@VM-0-16-centos downloads]# ls
php-8.0.2 php-8.0.2.tar.gz nginx-1.19.7 nginx-1.19.7.tar.gz swoole4.6.3.tar.gz
- 解压安装文件到downloads目录
tar -zxvf /usr/local/downloads/swoole4.6.3.tar.gz -C /usr/local/downloads
[root@VM-0-16-centos downloads]# tar -zxvf /usr/local/downloads/swoole4.6.3.tar.gz -C /usr/local/downloads
1.3 安装依赖
yum install libcurl-devel glibc-headers gcc-c++ pcre-devel
yum install automake autoconf bison
1.4 编译安装
- 用phpize生成configure
[root@VM-0-16-centos downloads]# cd /usr/local/downloads/swoole-src-4.6.3
[root@VM-0-16-centos swoole-src-4.6.3]# ls
clear.sh CODE-STYLE.md examples include mascot.png src tools
CMakeLists.txt config.m4 ext-src LICENSE package.xml SUPPORTED.md travis
code_format.sh CPPLINT.cfg gdbinit Makefile.frag README-CN.md tests
code_stats.sh CREDITS google-style.xml make.sh README.md thirdparty
存在configure文件就跳过,没有就用phpize生成configure
- 未安装php-devel运行phpize时报错
[root@VM-0-16-centos swoole-src-4.6.3] phpize
Can't find PHP headers in /usr/include/php
The php-devel package is required for use of this command.
- 查询php版本并安装相应的php-devel
yum -y install php-devel
[root@VM-0-16-centos swoole-src-4.6.3]# php -v
PHP 7.4.19 (cli) (built: May 4 2021 11:06:37) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Zend OPcache v7.4.19, Copyright (c), by Zend Technologies
[root@VM-0-16-centos swoole-src-4.6.3]# yum -y install php-devel
Last metadata expiration check: 11:46:59 ago on Sun 20 Feb 2022 03:24:28 AM CST.
Dependencies resolved.
====================================================================================================
Package Arch Version Repository Size
====================================================================================================
Installing:
php-devel x86_64 7.4.19-1.module_el8.5.0+815+1c4fd2e5 appstream 728 k
Installing dependencies:
cmake-filesystem x86_64 3.20.2-4.el8 appstream 44 k
libtool x86_64 2.4.6-25.el8 appstream 709 k
libxml2-devel x86_64 2.9.7-9.el8_4.2 appstream 1.0 M
xz-devel x86_64 5.2.4-3.el8 baseos 62 k
Transaction Summary
====================================================================================================
Install 5 Packages
Total download size: 2.5 M
Installed size: 17 M
Downloading Packages:
(1/5): cmake-filesystem-3.20.2-4.el8.x86_64.rpm 1.2 MB/s | 44 kB 00:00
(2/5): libtool-2.4.6-25.el8.x86_64.rpm 5.1 MB/s | 709 kB 00:00
(3/5): libxml2-devel-2.9.7-9.el8_4.2.x86_64.rpm 7.0 MB/s | 1.0 MB 00:00
(4/5): php-devel-7.4.19-1.module_el8.5.0+815+1c4fd2e5.x86_64.rpm 6.2 MB/s | 728 kB 00:00
(5/5): xz-devel-5.2.4-3.el8.x86_64.rpm 3.6 MB/s | 62 kB 00:00
----------------------------------------------------------------------------------------------------
Total 16 MB/s | 2.5 MB 00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : xz-devel-5.2.4-3.el8.x86_64 1/5
Installing : libtool-2.4.6-25.el8.x86_64 2/5
Running scriptlet: libtool-2.4.6-25.el8.x86_64 2/5
Installing : cmake-filesystem-3.20.2-4.el8.x86_64 3/5
Installing : libxml2-devel-2.9.7-9.el8_4.2.x86_64 4/5
Installing : php-devel-7.4.19-1.module_el8.5.0+815+1c4fd2e5.x86_64 5/5
Running scriptlet: php-devel-7.4.19-1.module_el8.5.0+815+1c4fd2e5.x86_64 5/5
Verifying : cmake-filesystem-3.20.2-4.el8.x86_64 1/5
Verifying : libtool-2.4.6-25.el8.x86_64 2/5
Verifying : libxml2-devel-2.9.7-9.el8_4.2.x86_64 3/5
Verifying : php-devel-7.4.19-1.module_el8.5.0+815+1c4fd2e5.x86_64 4/5
Verifying : xz-devel-5.2.4-3.el8.x86_64 5/5
Installed:
cmake-filesystem-3.20.2-4.el8.x86_64 libtool-2.4.6-25.el8.x86_64
libxml2-devel-2.9.7-9.el8_4.2.x86_64 php-devel-7.4.19-1.module_el8.5.0+815+1c4fd2e5.x86_64
xz-devel-5.2.4-3.el8.x86_64
Complete!
成功安装与php7.4.19匹配的php-devel 7.4.19
- 运行phpize命令生成configure文件
phpize
[root@VM-0-16-centos swoole-src-4.6.3]# phpize
Configuring for:
PHP Api Version: 20200930
Zend Module Api No: 20200930
Zend Extension Api No: 420200930
[root@VM-0-16-centos swoole-src-4.6.3]# ls
autom4te.cache code_stats.sh configure.ac gdbinit make.sh run-tests.php tools
build CODE-STYLE.md CPPLINT.cfg google-style.xml mascot.png src travis
clear.sh config.h.in CREDITS include package.xml SUPPORTED.md
CMakeLists.txt config.m4 examples LICENSE README-CN.md tests
code_format.sh configure ext-src Makefile.frag README.md thirdparty
成功生成configure文件
- 配置参数
[root@VM-0-16-centos swoole-src-4.6.3]# ./configure \
--enable-openssl \
--enable-swoole-json \
--enable-swoole-curl
参数详情参考官方说明
https://wiki.swoole.com/#/environment?id=%e7%bc%96%e8%af%91%e9%80%89%e9%a1%b9
- 编译安装
make && make install
----------------------------------------------------------------------
Libraries have been installed in:
/usr/local/downloads/swoole-src-4.6.3/modules
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
- add LIBDIR to the `LD_LIBRARY_PATH' environment variable
during execution
- add LIBDIR to the `LD_RUN_PATH' environment variable
during linking
- use the `-Wl,--rpath -Wl,LIBDIR' linker flag
- have your system administrator add LIBDIR to `/etc/ld.so.conf'
See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
Build complete.
Don't forget to run 'make test'.
Installing shared extensions: /usr/local/php8/lib/php/extensions/no-debug-non-zts-20200930/
Installing header files: /usr/local/php8/include/php/
查看安装的扩展文件
[root@VM-0-16-centos swoole-src-4.6.3]# cd /usr/local/php8/lib/php/extensions/no-debug-non-zts-20200930/
[root@VM-0-16-centos no-debug-non-zts-20200930]# ls
mysqli.so opcache.so pdo_mysql.so swoole.so
1.5 配置php启用swoole扩展
1.5.1 查看 php.ini 位置
php -i | grep php.ini
[root@VM-0-16-centos ~]# php -i | grep php.ini
Configuration File (php.ini) Path => /usr/local/php8/etc
Loaded Configuration File => /usr/local/php8/etc/php.ini
1.5.1 配置php扩展
vi /usr/local/php8/etc/php.ini
Dynamic Extensions 配置项中加入extension=swoole.so
;;;;;;;;;;;;;;;;;;;;;;
; Dynamic Extensions ;
;;;;;;;;;;;;;;;;;;;;;;
; If you wish to have an extension loaded automatically, use the following
; syntax:
;
; extension=modulename
;
; For example:
;
; extension=mysqli
;
; When the extension library to load is not located in the default extension
; directory, You may specify an absolute path to the library file:
;
; extension=/path/to/extension/mysqli.so
;
; Note : The syntax used in previous PHP versions ('extension=<ext>.so' and
; 'extension='php_<ext>.dll') is supported for legacy reasons and may be
; deprecated in a future PHP major version. So, when it is possible, please
; move to the new ('extension=<ext>) syntax.
;
; Notes for Windows environments :
;
; - Many DLL files are located in the extensions/ (PHP 4) or ext/ (PHP 5+)
; extension folders as well as the separate PECL DLL download (PHP 5+).
; Be sure to appropriately set the extension_dir directive.
extension=swoole.so
1.5.3 查看php加载swoole扩展情况
- 重启fpm
systemctl restart php-fpm
- 命令行查看swoole加载情况
php -m | grep swoole
[root@VM-0-16-centos ~]# php -m | grep swoole
swoole
php已经成功加载swoole扩展
- phpinfo页面查看swoole加载情况
1.5.4 加载报错处理
1.5.4.1 undefined symbol: php_json_exception_ce
[root@VM-0-16-centos ~]# php -m | grep swoole
PHP Warning: PHP Startup: Unable to load dynamic library 'swoole.so' (tried: /usr/lib64/php/modules/swoole.so (/usr/lib64/php/modules/swoole.so: undefined symbol: php_json_exception_ce), /usr/lib64/php/modules/swoole.so.so (/usr/lib64/php/modules/swoole.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0
报错是由swoole.so模块发出,说明swoole已经加载中,需要先加载php_json
- 查看/etc/php.d目录的ini文件
[root@VM-0-16-centos ~]# ls /etc/php.d
10-opcache.ini 20-exif.ini 20-json.ini 20-sockets.ini 30-mysqli.ini
20-bz2.ini 20-fileinfo.ini 20-mbstring.ini 20-sqlite3.ini 30-pdo_mysql.ini
20-calendar.ini 20-ftp.ini 20-mysqlnd.ini 20-tokenizer.ini 30-pdo_sqlite.ini
20-ctype.ini 20-gd.ini 20-pdo.ini 20-xml.ini 30-xmlreader.ini
20-curl.ini 20-gettext.ini 20-phar.ini 20-xmlwriter.ini opcache-default.blacklist
20-dom.ini 20-iconv.ini 20-simplexml.ini 20-xsl.ini
[root@VM-0-16-centos ~]# cat 20-json.ini
; Enable json extension module
extension=json
PHP默认加载的扩展配置不是在 /etc/php.ini 中,而是在 /etc/php.d/ 这个目录,当中的 .ini 文件是在 /etc/php.ini 加载完成后再加载的,所以extension=swoole.so 写在 /etc/php.ini 的Dynamic Extensions中,就是先加载了 swoole.so 再加载 json,导致了 swoole 找不到 php_json_exception_ce情况发生 。
- 去掉/etc/php.ini的extension=swoole.so
vim /etc/php.ini
#extension=swoole.so
- 在/etc/php.d/目录创建40-swoole.ini
vim 40-swoole.ini
extension=swoole
这里文件swoole.ini加入40-前缀,是为了让它最后加载,让数字小的先加载。
[root@VM-0-16-centos ~]# cd /etc/php.d/
[root@VM-0-16-centos ~]# ll
10-opcache.ini 20-exif.ini 20-json.ini 20-sockets.ini 30-mysqli.ini
20-bz2.ini 20-fileinfo.ini 20-mbstring.ini 20-sqlite3.ini 30-pdo_mysql.ini
20-calendar.ini 20-ftp.ini 20-mysqlnd.ini 20-tokenizer.ini 30-pdo_sqlite.ini
20-ctype.ini 20-gd.ini 20-pdo.ini 20-xml.ini 30-xmlreader.ini
20-curl.ini 20-gettext.ini 20-phar.ini 20-xmlwriter.ini opcache-default.blacklist
20-dom.ini 20-iconv.ini 20-simplexml.ini 20-xsl.ini
[root@VM-0-16-centos ~]# vim 40-swoole.ini
extension=swoole
:wq保存退出
[root@VM-0-16-centos ~]# ll
10-opcache.ini 20-exif.ini 20-json.ini 20-sockets.ini 30-mysqli.ini
20-bz2.ini 20-fileinfo.ini 20-mbstring.ini 20-sqlite3.ini 30-pdo_mysql.ini
20-calendar.ini 20-ftp.ini 20-mysqlnd.ini 20-tokenizer.ini 30-pdo_sqlite.ini
20-ctype.ini 20-gd.ini 20-pdo.ini 20-xml.ini 30-xmlreader.ini
20-curl.ini 20-gettext.ini 20-phar.ini 20-xmlwriter.ini 40-swoole.ini
20-dom.ini 20-iconv.ini 20-simplexml.ini 20-xsl.ini opcache-default.blacklist
- 重启fpm,查看swoole加载情况
systemctl restart php-fpm
- 命令行查看swoole加载情况
php -m | grep swoole
[root@VM-0-16-centos ~]# systemctl restart php-fpm
[root@VM-0-16-centos ~]# php -m | grep swoole
swoole
1.6 配置Nginx转发Swoole
1.6.1 Nginx与Swoole通信模式
[root@VM-0-16-centos ~]# find /etc/nginx/conf.d -name *.conf
/etc/nginx/conf.d/default.conf
/etc/nginx/conf.d/php-fpm.conf
- default.conf
默认站点配置文件- php-fpm.conf
php-fpm的负载分发upstream模块配置文件
[root@VM-0-16-centos ~]# vi /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
location ~ \.php$ {
root /usr/share/nginx/html;
fastcgi_pass unix:/dev/shm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
nginx遇到需要php处理的请求都会转发给php-fpm处理
- IP通信+网关代理
fastcgi_pass 127.0.0.1:9000;- unix sock通信+网关代理
fastcgi_pass unix:/run/php-fpm/www.sock
推荐把sock放在内存提高访问效率
fastcgi_pass unix:/dev/shm/www.sock- upstream负载均衡+反向代理
upstream_name :自定义upstream名称
proxy_pass http://upstream_name;
1.6.2 Nginx负载均衡模块 upstream
upstream模块,使nginx跨越单机的运算限制,分发给不同主机处理php业务,实现网络数据的接收、处理和转发。
1.6.2.1 FPM upstream模块配置
FPM是php系统自带的处理模块,我们看下它的upstream默认配置。
cat /etc/nginx/conf.d/php-fpm.conf
# PHP-FPM FastCGI server
# network or unix domain socket configuration
# sock
upstream php-fpm {
server unix:/run/php-fpm/www.sock;
}
# TCPIP
upstream php-fpm-tcp {
server 127.0.0.1:9000 weight=3 max_conns=2000;
server 127.0.0.2:9000 weight=2 max_conns=2000 down;
#server 127.0.0.3:9000 backup max_conns=1000;
}
1.6.2.2 swoole upstream模块配置
新建conf配置swoole的upstream,让nginx把php请求发送给swoole处理。
vim /etc/nginx/conf.d/swoole_http.conf
# 这是swoole的负载分发配置
upstream swoole_http{
#ip_hash;
server 127.0.0.1:9501 weight=3 max_conns=2000;
server 127.0.0.2:9501 weight=2 max_conns=2000 down;
#server 127.0.0.3:9501 backup max_conns=1000;
}
1.6.2.3 upstream 模块参数解析
- 负载均衡分配方式
- 轮询 默认
每个请求按顺序分配到不同后端服务器- ip_hash
哈希表分配负载,根据散列算法分配不同用户固定访问一个后端服务器,相同的客户端ip请求相同的服务器,解决session一致问题
有条件架构独立Redis服务器,缓存所有后端服务器的session,也能解决session一致问题- weight
权重数值越大,负载分配几率越大
不设权重,默认把请求轮循负载到各个服务器
轮询,ip_hash,权重三种分配方式不能同时生效,三选一
- 参数解析
- max_conns
最大连接数
限制服务器允许的最大连接数量,超过的连接不会分配,轮询分配到其他服务器。默认为0为不限制。- backup
后备服务器
只有其他所有swoole服务器都负载饱和或当机才被启用加与负载- down
当机标记
有服务器当机,nginx自动标记服务器,排除down服务器的负载分配- max_fails 单位时间内重试连接次数
- fail_timeout 允许重试连接的单位时间和请求失败等待轮询的单位时间
在单位周期fail_timeout内,重试连接达到max_fails次数,nginx把此服务器节点标记为宕机不可用(down),将连接转到其他服务器节点;
有新的连接符合下一个周期(单位时间为fail_timeout)再一次去请求,判断是否连接是否成功,恢复此节点。
1.6.3 Nginx 转发 PHP请求
1.6.3.1 FMP 的php请求转发
# php-fpm 管理模式处理php请求配置
location ~ \.php$ {
#网关代理转发请求到unix sock
#fastcgi_pass unix:/dev/shm/php-fpm.sock;
#网关代理转发请求到TCPIP
fastcgi_pass 127.0.0.1:9000;
#网关代理转发请求到upstream
#fastcgi_pass php-fpm
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
正则匹配所有对.php文件的请求,由fastcgi管理程序转发给fpm-php进程处理
正则表达式匹配
- = 精确匹配;
- ^~ 提高前缀字符串的匹配优先级;
- ~ 区分大小写的正则表达式匹配;
- ~* 不区分大小写的正则表达式匹配;
- / 通用匹配(因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求),如果没有其它匹配,任何请求都会匹配到。
匹配优先级
( = ) >( ^~ ) > ( ~) > ( ~* ) > ( / ) > ( 长字符串 ) > ( 短字符串 )
1.6.3.2 Swoole 的php请求转发配置
- 只转发php请求给Swoole
# swoole 框架处理php请求配置
location ~ \.php$ {
proxy_http_version 1.1;
proxy_set_header Connection "keep-alive";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
# 反向代理转发请求到upstream节点
proxy_pass http://swoole_http;
# 反向代理转发请求到TCPIP
#proxy_pass http://127.0.0.1:9501;
}
- 转发所有请求给Swoole
配置1
# swoole 框架处理所有请求配置
location / {
proxy_http_version 1.1;
proxy_set_header Connection "keep-alive";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
if (!-e $request_filename) {
# 反向代理转发请求到upstream节点
proxy_pass http://swoole_http;
# 反向代理转发请求到TCPIP
#proxy_pass http://127.0.0.1:9501;
}
}
配置2
location / {
# $uri文件存在,Nginx处理,否则交给Swoole处理
try_files $uri @swoole;
}
location @swoole {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Connection "keep-alive";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
1.6.3 测试Swoole http服务
[root@VM-0-16-centos ~]# mkdir /opt/swoole
[root@VM-0-16-centos ~]# cd /opt/swoole
[root@VM-0-16-centos swoole]# vi http_test.php
- 创建swoole http服务器测试脚本
<?php
$http = new Swoole\Http\Server('0.0.0.0', 9501);
$http->on('Request', function (