• 对于注定会优秀的人来说,他所需要的,只是时间!
  • 手懒得,必受贫穷,手勤的,必得富足----《圣经》
  • 帮助别人,成就自己。愿君在本站能真正有所收获!
  • 如果你在本站中发现任何问题,欢迎留言指正!
  • 宝剑锋从磨砺出,梅花香自苦寒来!

由Nginx集中代理分散的PHP集群的实践

网站服务 eryajf 1个月前 (01-24) 206°C 已收录 0个评论
本文预计阅读时间 14 分钟
文章目录[隐藏]

1,以往

以往的PHP项目处理方案大多沿用了经典的lnmp,然后几乎有PHP的主机都会配套一个Nginx,接着有多少个PHP,就会有多少个Nginx,然后lb后边就得挂上这所有的Nginx。

但事实上还可以用如下办法来将PHP分散管理。

2,现在

Nginx主配置像配置Java应用一般反代转发给PHP服务:

upstream php-fpm {
   server 127.0.0.1:9006 weight=6 max_fails=300 fail_timeout=5s;
   server 127.0.0.1:9007 weight=6 max_fails=300 fail_timeout=5s;
}

server{
    listen 80;
    server_name 10.3.7.7;

    proxy_connect_timeout 300;
    proxy_read_timeout 300;
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;

    location / {
        root /data/www/liql;
        index index.php index.html index.htm;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        try_files $uri $uri/ /index.php?$query_string;
    }

   location ~ \.php($|/) {
        root /data/www/liql;
        index index.php index.html index.htm;
        fastcgi_pass  php-fpm;
        fastcgi_index  index.php;
        fastcgi_split_path_info ^(.+\.php)(.*)$;
        include  fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    }
}

这样只需要将代码放入到PHP容器内即可:

$ cat liql/index.php
<?php
    phpinfo();
?>

$ cat Dockerfile
FROM reg.weipaitang.com/multienv/wpt_phpfpm:7.2.34
COPY . /data/www/

然后重新打镜像:

docker build -t aaa .

启动两个容器进行访问,可以发现权重很均衡的取到了两个PHP容器之内:

{"remote_addr": "10.105.201.43","@timestamp": "2021-01-24T17:14:27+08:00","upstream_addr": "127.0.0.1:9006","request_uri": "/","verb": "GET","httpversion": "HTTP/1.1","response": "200", "body_bytes_sent": "28892", "referrer": "", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", "http_x_forwarded_for": "", "server_name": "10.3.7.7","request_time": "0.003","upstream_response_time": "0.003","realpath_root": "","cookie": "grafana_session=02bc6ce5e1489781ff5ed00ef9fb61ca","request_body": "","nginx_version": "1.13.6","scheme": "http"}
{"remote_addr": "10.105.201.43","@timestamp": "2021-01-24T17:14:28+08:00","upstream_addr": "127.0.0.1:9007","request_uri": "/","verb": "GET","httpversion": "HTTP/1.1","response": "200", "body_bytes_sent": "28895", "referrer": "", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", "http_x_forwarded_for": "", "server_name": "10.3.7.7","request_time": "0.004","upstream_response_time": "0.004","realpath_root": "","cookie": "grafana_session=02bc6ce5e1489781ff5ed00ef9fb61ca","request_body": "","nginx_version": "1.13.6","scheme": "http"}

3,另外

  • 在测试过程中发现,如果代理的两个容器有一个没有起来,竟丝毫不影响服务的访问,转发的方式也非常有意思,从日志中观察:
    {"remote_addr": "10.105.201.43","@timestamp": "2021-01-24T17:36:27+08:00","upstream_addr": "127.0.0.1:9006","request_uri": "/","verb": "GET","httpversion": "HTTP/1.1","response": "200", "body_bytes_sent": "28898", "referrer": "", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", "http_x_forwarded_for": "", "server_name": "10.3.7.7","request_time": "0.004","upstream_response_time": "0.004","realpath_root": "/data/www/liql","cookie": "grafana_session=02bc6ce5e1489781ff5ed00ef9fb61ca","request_body": "","nginx_version": "1.13.6","scheme": "http"}
    {"remote_addr": "10.105.201.43","@timestamp": "2021-01-24T17:36:29+08:00","upstream_addr": "127.0.0.1:9007, 127.0.0.1:9006","request_uri": "/","verb": "GET","httpversion": "HTTP/1.1","response": "200", "body_bytes_sent": "28899", "referrer": "", "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", "http_x_forwarded_for": "", "server_name": "10.3.7.7","request_time": "0.004","upstream_response_time": "0.000, 0.004","realpath_root": "/data/www/liql","cookie": "grafana_session=02bc6ce5e1489781ff5ed00ef9fb61ca","request_body": "","nginx_version": "1.13.6","scheme": "http"}
    

    注意日志中的 upstream_addr字段,第一条请求被9006端口正常解析,第二条的解析竟然两个端口都有,也就是说,9007端口不存在或者无法正常解析的时候,此请求会被正常的9006给解析掉,看错误日志里记录下了9007的错误:

    2021/01/24 17:36:29 [error] 24165#24165: *394 connect() failed (111: Connection refused) while connecting to upstream, client: 10.105.201.43, server: 10.3.7.7, request: "GET / HTTP/1.1", upstream: "fastcgi://127.0.0.1:9007", host: "10.3.7.7"
    
  • 注意代码的存放位置
    • 这里有两点需要注意,一个是 root指令不要放在location外边,这里是纯PHP解析,如果放到外边,请求的时候总会报一个本地找不到的错误:
    2021/01/24 17:21:51 [crit] 23563#23563: *347 realpath() "/data/www/liql" failed (2: No such file or directory) while logging request, client: 10.105.201.43, server: 10.3.7.7, request: "GET / HTTP/1.1", upstream: "fastcgi://127.0.0.1:9006", host: "10.3.7.7"
    

    这个时候把 root指令放到location内部就不会报这个错误了。

    • 另外注意,代码是存放在PHP所在主机上的,而非Nginx所在主机,因为.php结尾的请求都是通过fast_cgi解析的,而非Nginx,这里千万不要用传统的http代理来理解了。

    所以这个地方的处理流程应该是这样的:

    www.example.com
            |
            |
          Nginx
            |
            |
    路由到www.example.com/index.php
            |
            |
    加载nginx的fast-cgi模块
            |
            |
    fast-cgi监听127.0.0.1:9006地址
            |
            |
    www.example.com/index.php请求到达127.0.0.1:9000
            |
            |
    php-fpm 监听127.0.0.1:9000
            |
            |
    php-fpm 接收到请求,启用worker进程处理请求
            |
            |
    php-fpm 在给定的root地址下解析PHP源码,将结果返回给nginx
            |
            |
    nginx将结果通过http返回给浏览器
    

    这样,就能很清晰地解析整个处理链路了。

    本文实验探索的主要意义在于,在这种基础之下,我们就可以摒弃掉以往处理PHP业务场景的固化思维,从而将Nginx这层网关像处理Java应用那样一般,集中对PHP应用进行处理了,以实现集中化管理,更加便于横向扩展与运维。


weinxin
扫码订阅本站,第一时间获得更新
微信扫描二维码,订阅我们网站的动态,另外不定时发送WordPress小技巧,你可以随时退订,欢迎订阅哦~

二丫讲梵 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明由Nginx集中代理分散的PHP集群的实践
喜欢 (1)
[如果想支持本站,可支付宝赞助]
分享 (0)
eryajf
关于作者:
学无止境,我愿意无止境学。书山有路,我愿意举身投火,淬炼成金!永远不要忘记,激情的奋进,就是美好的未来!

您必须 登录 才能发表评论!