[已解决] 关于windows+nginx+php配置问题,现在接口请求会阻塞

ken124

问题描述

Windows Server 2022 Datacenter
nginx 1.22
php ts 8.3
session用的是redis 5.0.14.1,
代码框架用的是thinkphp5.0

具体的现象是同一个会话请求时, 前面的请求处理会阻塞,下一个异步进来的请求,
不同会话之间不会相互阻塞

php API 测试的代码很简单

{
    function test(){
        echo "hello world";
    }

    function sleep1(){
        //单存输出 <pre> 标签方便测试
        pre();
        //直接关闭session
        session_write_close();
        if (session_status() === PHP_SESSION_ACTIVE) {
            echo_ln("session 开启了");
        } else {
            echo_ln("session 没启动");
        }

        // 在需要的地方检查session_write_close()是否被调用
        if (session_status() === PHP_SESSION_ACTIVE && !headers_sent()) {
            // 如果没有输出到浏览器并且Session处于活动状态,则调用session_write_close()
            // session_write_close();
            echo_ln("session 没关闭");
        }

        // echo_ln 单存的在 输出语句后面补上换行符
        echo_ln( "strat:" . time() );
        sleep(10);
        echo_ln( "end:" . time() );
    }
}

同一个浏览器开两个标签页,手动的,几乎同时刷新,会发现第二个被刷新的页面一定比前一个慢10秒才开始执行
已经配置过 php.ini , nginx.conf

nginx.conf


#user  nobody;
worker_processes  8;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

events {
    worker_connections  1024;
    multi_accept on;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                     '$status $body_bytes_sent "$http_referer" '
                     '"$http_user_agent" "$http_x_forwarded_for"';

    log_format detailed '$remote_addr - $remote_user [$time_local] "$request" '
                   '$status $body_bytes_sent "$http_referer" '
                   '"$http_user_agent" "$http_x_forwarded_for" '
                   'upstream: $upstream_addr';

    # access_log  logs/access.log  main;
    access_log  logs/access.log detailed;

    server_names_hash_bucket_size 128;
    client_header_buffer_size 32k;
    large_client_header_buffers 4 32k;
    client_max_body_size 8m;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    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;

    #为了让nginx在windows系统下支持高并发处理fastcgi
    #手动添加多个监听ip
    #加多少个监听ip就表示加多少监听进程协助处理请求
    #直接加32个
    upstream phpfastcgi_proxy{
        #最少连接数负载均衡
        least_conn;
        server 127.0.0.1:9000;
        server 127.0.0.1:9001;
        server 127.0.0.1:9002;
        server 127.0.0.1:9003;
        # server 127.0.0.1:9004;
        # server 127.0.0.1:9005;
        # server 127.0.0.1:9006;
        # server 127.0.0.1:9007;
        # server 127.0.0.1:9008;
        # server 127.0.0.1:9009;
        # server 127.0.0.1:9010;
        # server 127.0.0.1:9011;
        # server 127.0.0.1:9012;
        # server 127.0.0.1:9013;
        # server 127.0.0.1:9014;
        # server 127.0.0.1:9015;
        # server 127.0.0.1:9016;
        # server 127.0.0.1:9017;
        # server 127.0.0.1:9018;
        # server 127.0.0.1:9019;
        # server 127.0.0.1:9020;
        # server 127.0.0.1:9021;
        # server 127.0.0.1:9022;
        # server 127.0.0.1:9023;
        # server 127.0.0.1:9024;
        # server 127.0.0.1:9025;
        # server 127.0.0.1:9026;
        # server 127.0.0.1:9027;
        # server 127.0.0.1:9028;
        # server 127.0.0.1:9029;
        # server 127.0.0.1:9030;
        # server 127.0.0.1:9031;
    }

    #开发
    server {
        listen       8000;
        server_name  location;

        index index.php;
        root D:\webapp\development\public;

        location / {
            if (!-e $request_filename){
                rewrite ^/(.*)$ /index.php/$1 last;
            }
        }

        location ~ .*\.php {
            if (!-e $document_root$fastcgi_script_name) {
                ##此处直接返回404错误
                ##你也可以rewrite 到新地址去,然后break;
                return 404;
            }
            #修改监听ip 为 phpfastcgi_proxy
            fastcgi_pass   phpfastcgi_proxy;
            fastcgi_index  index.php;
            fastcgi_split_path_info  ^(.+\.php)(.*)$;
            fastcgi_param PATH_INFO $fastcgi_path_info;

            fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        # location / {
        #     root   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   html;
        }
    }

    server {
        listen       8001;
        server_name  location;

        index index.php;
        root D:\webapp\development2\public;

        location / {
            if (!-e $request_filename){
                rewrite ^/(.*)$ /index.php/$1 last;
            }
        }

        location ~ .*\.php {
            if (!-e $document_root$fastcgi_script_name) {
                ##此处直接返回404错误
                ##你也可以rewrite 到新地址去,然后break;
                return 404;
            }
            fastcgi_pass   phpfastcgi_proxy;
            fastcgi_index  index.php;
            fastcgi_split_path_info  ^(.+\.php)(.*)$;
            fastcgi_param PATH_INFO $fastcgi_path_info;

            fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        # location / {
        #     root   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   html;
        }
    }

    #生产
    server {
        listen       88;
        server_name  location;

        index index.php;
        root D:\webapp\production\public;

        location / {
            if (!-e $request_filename){
                rewrite ^/(.*)$ /index.php/$1 last;
            }
        }

        location ~ .*\.php {
            if (!-e $document_root$fastcgi_script_name) {
                ##此处直接返回404错误
                ##你也可以rewrite 到新地址去,然后break;
                return 404;
            }
            fastcgi_pass   phpfastcgi_proxy;
            fastcgi_index  index.php;
            fastcgi_split_path_info  ^(.+\.php)(.*)$;
            fastcgi_param PATH_INFO $fastcgi_path_info;

            fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        # location / {
        #     root   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   html;
        }
    }
}

目前尚不知是php-cgi在windows系统下的根本性特性还是我配置哪里写错
有查到一个说法,windows下只有apache才能让php不阻塞执行,但是尚未验证,
请有经验的同行帮忙解答问题

问题解决

结论如一楼评论,需要精确控制每次session变量的启动和关闭
然后我的php举例并不能模拟实际场景
一般情况下的阻塞场景,基本是请求数据库或其他应用程序,比较耗时
而 sleep函数 比较特殊,是真的直接阻塞整个进程或线程,原理不深究

227 1 0
1个回答

six

php-fpm 同一会话session访问是串行的,上一个请求需要结束session后,下一个请求才能访问session。结局方案,需要的时候才用session_start()开启session,session不需要再使用了立刻执行session_write_close()关闭session

🔝