没有不值得去解决的问题,也没有不值得去学习的技术!

Analyzing and Resolving Serial and Parallel Support for Nginx + php-fpm on Windows 10 and CentOS 8

Edit the Nginx configuration file and modify the server_name value to: api.channel-pub.wjdev.chinamcloud.cn localhost, so that CURLing another request (http://localhost) from within a request (https://api.channel-pub.wjdev.chinamcloud.cn) (7 requests in total) directly targets the local machine, saving network overhead. The overall response time is 1956ms, about 2 seconds, which meets expectations.

1. Behavior of Nginx + php-fpm on Windows 10: when CURLing another request (http://api.channel-pub-api.localhost) from within a request (http://api.channel-pub-api.localhost), the following error occurs: fopen(http://api.channel-pub-api.localhost/qq/v1/articles/standard?group_id=015ce30b116ce86058fa6ab4fea4ac63): failed to open stream: HTTP request failed! . See Figure 1

Behavior of Nginx + php-fpm on Windows 10: when CURLing another request (http://api.channel-pub-api.localhost) from within a request (http://api.channel-pub-api.localhost), the following error occurs: fopen(http://api.channel-pub-api.localhost/qq/v1/articles/standard?group_id=015ce30b116ce86058fa6ab4fea4ac63): failed to open stream: HTTP request failed! .
Figure 1
JSON

{
    "name": "HTTP Client Exception",
    "message": "fopen(http://api.channel-pub-api.localhost/qq/v1/articles/standard?group_id=015ce30b116ce86058fa6ab4fea4ac63): failed to open stream: HTTP request failed! ",
    "code": 2,
    "type": "yii\\httpclient\\Exception",
    "file": "E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2-httpclient\\src\\StreamTransport.php",
    "line": 68,
    "stack-trace": [
        "#0 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2-httpclient\\src\\Transport.php(41): yii\\httpclient\\StreamTransport->send(Object(yii\\httpclient\\Request))",
        "#1 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2-httpclient\\src\\Client.php(259): yii\\httpclient\\Transport->batchSend(Array)",
        "#2 E:\\wwwroot\\channel-pub-api-feature-task-group\\common\\logics\\http\\channel_pub_api\\Article.php(55): yii\\httpclient\\Client->batchSend(Array)",
        "#3 E:\\wwwroot\\channel-pub-api-feature-task-group\\common\\services\\TaskGroupService.php(117): common\\logics\\http\\channel_pub_api\\Article->batchPostArticlesStandard('015ce30b116ce86...', Array)",
        "#4 E:\\wwwroot\\channel-pub-api-feature-task-group\\api\\filters\\TaskGroupFilter.php(45): common\\services\\TaskGroupService::createMultipleSync(Array)",
        "#5 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2\\base\\ActionFilter.php(92): api\\filters\\TaskGroupFilter->afterAction(Object(api\\rests\\task_group\\CreateAction), Array)",
        "#6 [internal function]: yii\\base\\ActionFilter->afterFilter(Object(yii\\base\\ActionEvent))",
        "#7 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2\\base\\Component.php(627): call_user_func(Array, Object(yii\\base\\ActionEvent))",
        "#8 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2\\base\\Controller.php(305): yii\\base\\Component->trigger('afterAction', Object(yii\\base\\ActionEvent))",
        "#9 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2\\rest\\Controller.php(76): yii\\base\\Controller->afterAction(Object(api\\rests\\task_group\\CreateAction), Array)",
        "#10 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2\\base\\Controller.php(159): yii\\rest\\Controller->afterAction(Object(api\\rests\\task_group\\CreateAction), Array)",
        "#11 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2\\base\\Module.php(528): yii\\base\\Controller->runAction('create', Array)",
        "#12 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2\\web\\Application.php(103): yii\\base\\Module->runAction('v1/task-group/c...', Array)",
        "#13 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2\\base\\Application.php(386): yii\\web\\Application->handleRequest(Object(yii\\web\\Request))",
        "#14 E:\\wwwroot\\channel-pub-api-feature-task-group\\api\\web\\index.php(17): yii\\base\\Application->run()",
        "#15 {main}"
    ],
    "previous": {
        "name": "PHP Warning",
        "message": "fopen(http://api.channel-pub-api.localhost/qq/v1/articles/standard?group_id=015ce30b116ce86058fa6ab4fea4ac63): failed to open stream: HTTP request failed! ",
        "code": 2,
        "type": "yii\\base\\ErrorException",
        "file": "E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2-httpclient\\src\\StreamTransport.php",
        "line": 61,
        "stack-trace": [
            "#0 [internal function]: yii\\base\\ErrorHandler->handleError(2, 'fopen(http://ap...', 'E:\\\\wwwroot\\\\chan...', 61, Array)",
            "#1 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2-httpclient\\src\\StreamTransport.php(61): fopen('http://api.chan...', 'rb', false, Resource id #205)",
            "#2 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2-httpclient\\src\\Transport.php(41): yii\\httpclient\\StreamTransport->send(Object(yii\\httpclient\\Request))",
            "#3 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2-httpclient\\src\\Client.php(259): yii\\httpclient\\Transport->batchSend(Array)",
            "#4 E:\\wwwroot\\channel-pub-api-feature-task-group\\common\\logics\\http\\channel_pub_api\\Article.php(55): yii\\httpclient\\Client->batchSend(Array)",
            "#5 E:\\wwwroot\\channel-pub-api-feature-task-group\\common\\services\\TaskGroupService.php(117): common\\logics\\http\\channel_pub_api\\Article->batchPostArticlesStandard('015ce30b116ce86...', Array)",
            "#6 E:\\wwwroot\\channel-pub-api-feature-task-group\\api\\filters\\TaskGroupFilter.php(45): common\\services\\TaskGroupService::createMultipleSync(Array)",
            "#7 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2\\base\\ActionFilter.php(92): api\\filters\\TaskGroupFilter->afterAction(Object(api\\rests\\task_group\\CreateAction), Array)",
            "#8 [internal function]: yii\\base\\ActionFilter->afterFilter(Object(yii\\base\\ActionEvent))",
            "#9 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2\\base\\Component.php(627): call_user_func(Array, Object(yii\\base\\ActionEvent))",
            "#10 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2\\base\\Controller.php(305): yii\\base\\Component->trigger('afterAction', Object(yii\\base\\ActionEvent))",
            "#11 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2\\rest\\Controller.php(76): yii\\base\\Controller->afterAction(Object(api\\rests\\task_group\\CreateAction), Array)",
            "#12 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2\\base\\Controller.php(159): yii\\rest\\Controller->afterAction(Object(api\\rests\\task_group\\CreateAction), Array)",
            "#13 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2\\base\\Module.php(528): yii\\base\\Controller->runAction('create', Array)",
            "#14 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2\\web\\Application.php(103): yii\\base\\Module->runAction('v1/task-group/c...', Array)",
            "#15 E:\\wwwroot\\channel-pub-api-feature-task-group\\vendor\\yiisoft\\yii2\\base\\Application.php(386): yii\\web\\Application->handleRequest(Object(yii\\web\\Request))",
            "#16 E:\\wwwroot\\channel-pub-api-feature-task-group\\api\\web\\index.php(17): yii\\base\\Application->run()",
            "#17 {main}"
        ]
    }
}

2. Edit the Nginx configuration file and copy server: API as server: LOCALHOST API. Adjust listen 81, server_name localhost, and fastcgi_pass 127.0.0.1:9001. There are 3 configuration values in total. See Figure 2 and Figure 3

Edit the Nginx configuration file and copy server: API as server: LOCALHOST API. Adjust listen 81, server_name localhost
Figure 2

 

Edit the Nginx configuration file and copy server: API as server: LOCALHOST API. Adjust fastcgi_pass 127.0.0.1:9001
Figure 3
Nginx

## FRONTEND ##
server {
    charset utf-8;

	client_max_body_size 200m;
	client_body_buffer_size 1024k;

	fastcgi_read_timeout 180s;

    listen 80; ## listen for ipv4
    #listen [::]:80 default_server ipv6only=on; ## listen for ipv6

    server_name www.channel-pub-api.localhost www.channel-pub-api-localhost.chinamcloud.cn auth.channel-pub.wjdev.chinamcloud.cn;
    root        E:/wwwroot/channel-pub-api-feature-task-group/frontend/web;
    index       index.php;

    access_log  logs/www.channel-pub-api.localhost.access.log;
    error_log   logs/www.channel-pub-api.localhost.error.log;

	location / {
		# Redirect everything that isn't a real file to index.php
		try_files $uri $uri/ /index.php$is_args$args;
	}

	# uncomment to avoid processing of calls to non-existing static files by Yii
	#location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
	#    try_files $uri =404;
	#}
	#error_page 404 /404.html;

	# deny accessing php files for the /assets directory
	location ~ ^/assets/.*\.php$ {
		deny all;
	}

	location ~ \.php$ {
		include fastcgi_params;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		fastcgi_pass 127.0.0.1:9000;
		#fastcgi_pass unix:/var/run/php5-fpm.sock;
		try_files $uri =404;
	}

	location ~* /\. {
		deny all;
	}
}

## API ##
server {
    charset utf-8;

	client_max_body_size 200m;
	client_body_buffer_size 1024k;

	fastcgi_read_timeout 180s;

    listen 80; ## listen for ipv4
    #listen [::]:80 default_server ipv6only=on; ## listen for ipv6

    server_name api.channel-pub-api.localhost api.channel-pub-api-localhost.chinamcloud.cn;

    root E:/wwwroot/channel-pub-api-feature-task-group;
    index index.php;

    access_log  logs/api.channel-pub-api.localhost.access.log;
    error_log   logs/api.channel-pub-api.localhost.error.log;

	location / {
        root E:/wwwroot/channel-pub-api-feature-task-group/api/web;
        try_files $uri $uri/ /api/web/index.php$is_args$args;

        # omit static files logging, and if they don't exist, avoid processing by Yii (uncomment if necessary)
        #location ~ ^/.+\.(css|js|ico|png|jpe?g|gif|svg|ttf|mp4|mov|swf|pdf|zip|rar)$ {
        #    log_not_found off;
        #    access_log off;
        #    try_files $uri =404;
        #}

        location ~ ^/assets/.+\.php(/|$) {
            deny all;
        }
    }

    location /baijia {
        alias E:/wwwroot/channel-pub-api-feature-task-group/baijia/web/;

        # redirect to the URL without a trailing slash (uncomment if necessary)
        #location = /baijia/ {
        #    return 301 /baijia;
        #}

        # prevent the directory redirect to the URL with a trailing slash
        location = /baijia {
            # if your location is "/baijia", try use "/baijia/baijia/web/index.php$is_args$args"
            # bug ticket: https://trac.nginx.org/nginx/ticket/97
            try_files $uri /baijia/baijia/web/index.php$is_args$args;
        }

        # if your location is "/baijia", try use "/baijia/baijia/web/index.php$is_args$args"
        # bug ticket: https://trac.nginx.org/nginx/ticket/97
        try_files $uri $uri/ /baijia/baijia/web/index.php$is_args$args;

        # omit static files logging, and if they don't exist, avoid processing by Yii (uncomment if necessary)
        #location ~ ^/baijia/.+\.(css|js|ico|png|jpe?g|gif|svg|ttf|mp4|mov|swf|pdf|zip|rar)$ {
        #    log_not_found off;
        #    access_log off;
        #    try_files $uri =404;
        #}

        location ~ ^/baijia/assets/.+\.php(/|$) {
            deny all;
        }
    }

	location /customize {
        alias E:/wwwroot/channel-pub-api-feature-task-group/customize/web/;

        # redirect to the URL without a trailing slash (uncomment if necessary)
        #location = /customize/ {
        #    return 301 /customize;
        #}

        # prevent the directory redirect to the URL with a trailing slash
        location = /customize {
            # if your location is "/customize", try use "/customize/customize/web/index.php$is_args$args"
            # bug ticket: https://trac.nginx.org/nginx/ticket/97
            try_files $uri /customize/customize/web/index.php$is_args$args;
        }

        # if your location is "/customize", try use "/customize/customize/web/index.php$is_args$args"
        # bug ticket: https://trac.nginx.org/nginx/ticket/97
        try_files $uri $uri/ /customize/customize/web/index.php$is_args$args;

        # omit static files logging, and if they don't exist, avoid processing by Yii (uncomment if necessary)
        #location ~ ^/customize/.+\.(css|js|ico|png|jpe?g|gif|svg|ttf|mp4|mov|swf|pdf|zip|rar)$ {
        #    log_not_found off;
        #    access_log off;
        #    try_files $uri =404;
        #}

        location ~ ^/customize/assets/.+\.php(/|$) {
            deny all;
        }
    }

	location /netease {
        alias E:/wwwroot/channel-pub-api-feature-task-group/netease/web/;

        # redirect to the URL without a trailing slash (uncomment if necessary)
        #location = /netease/ {
        #    return 301 /netease;
        #}

        # prevent the directory redirect to the URL with a trailing slash
        location = /netease {
            # if your location is "/netease", try use "/netease/netease/web/index.php$is_args$args"
            # bug ticket: https://trac.nginx.org/nginx/ticket/97
            try_files $uri /netease/netease/web/index.php$is_args$args;
        }

        # if your location is "/netease", try use "/netease/netease/web/index.php$is_args$args"
        # bug ticket: https://trac.nginx.org/nginx/ticket/97
        try_files $uri $uri/ /netease/netease/web/index.php$is_args$args;

        # omit static files logging, and if they don't exist, avoid processing by Yii (uncomment if necessary)
        #location ~ ^/netease/.+\.(css|js|ico|png|jpe?g|gif|svg|ttf|mp4|mov|swf|pdf|zip|rar)$ {
        #    log_not_found off;
        #    access_log off;
        #    try_files $uri =404;
        #}

        location ~ ^/netease/assets/.+\.php(/|$) {
            deny all;
        }
    }

    location /qq {
        alias E:/wwwroot/channel-pub-api-feature-task-group/qq/web/;

        # redirect to the URL without a trailing slash (uncomment if necessary)
        #location = /qq/ {
        #    return 301 /qq;
        #}

        # prevent the directory redirect to the URL with a trailing slash
        location = /qq {
            # if your location is "/qq", try use "/qq/qq/web/index.php$is_args$args"
            # bug ticket: https://trac.nginx.org/nginx/ticket/97
            try_files $uri /qq/qq/web/index.php$is_args$args;
        }

        # if your location is "/qq", try use "/qq/qq/web/index.php$is_args$args"
        # bug ticket: https://trac.nginx.org/nginx/ticket/97
        try_files $uri $uri/ /qq/qq/web/index.php$is_args$args;

        # omit static files logging, and if they don't exist, avoid processing by Yii (uncomment if necessary)
        #location ~ ^/qq/.+\.(css|js|ico|png|jpe?g|gif|svg|ttf|mp4|mov|swf|pdf|zip|rar)$ {
        #    log_not_found off;
        #    access_log off;
        #    try_files $uri =404;
        #}

        location ~ ^/qq/assets/.+\.php(/|$) {
            deny all;
        }
    }

	location /weibo {
        alias E:/wwwroot/channel-pub-api-feature-task-group/weibo/web/;

        # redirect to the URL without a trailing slash (uncomment if necessary)
        #location = /weibo/ {
        #    return 301 /weibo;
        #}

        # prevent the directory redirect to the URL with a trailing slash
        location = /weibo {
            # if your location is "/weibo", try use "/weibo/weibo/web/index.php$is_args$args"
            # bug ticket: https://trac.nginx.org/nginx/ticket/97
            try_files $uri /weibo/weibo/web/index.php$is_args$args;
        }

        # if your location is "/weibo", try use "/weibo/weibo/web/index.php$is_args$args"
        # bug ticket: https://trac.nginx.org/nginx/ticket/97
        try_files $uri $uri/ /weibo/weibo/web/index.php$is_args$args;

        # omit static files logging, and if they don't exist, avoid processing by Yii (uncomment if necessary)
        #location ~ ^/weibo/.+\.(css|js|ico|png|jpe?g|gif|svg|ttf|mp4|mov|swf|pdf|zip|rar)$ {
        #    log_not_found off;
        #    access_log off;
        #    try_files $uri =404;
        #}

        location ~ ^/weibo/assets/.+\.php(/|$) {
            deny all;
        }
    }

	location /wx {
        alias E:/wwwroot/channel-pub-api-feature-task-group/wx/web/;

        # redirect to the URL without a trailing slash (uncomment if necessary)
        #location = /wx/ {
        #    return 301 /wx;
        #}

        # prevent the directory redirect to the URL with a trailing slash
        location = /wx {
            # if your location is "/wx", try use "/wx/wx/web/index.php$is_args$args"
            # bug ticket: https://trac.nginx.org/nginx/ticket/97
            try_files $uri /wx/wx/web/index.php$is_args$args;
        }

        # if your location is "/wx", try use "/wx/wx/web/index.php$is_args$args"
        # bug ticket: https://trac.nginx.org/nginx/ticket/97
        try_files $uri $uri/ /wx/wx/web/index.php$is_args$args;

        # omit static files logging, and if they don't exist, avoid processing by Yii (uncomment if necessary)
        #location ~ ^/wx/.+\.(css|js|ico|png|jpe?g|gif|svg|ttf|mp4|mov|swf|pdf|zip|rar)$ {
        #    log_not_found off;
        #    access_log off;
        #    try_files $uri =404;
        #}

        location ~ ^/wx/assets/.+\.php(/|$) {
            deny all;
        }
    }

	location ~ ^/.+\.php(/|$) {
        rewrite (?!^/((api|baijia|customize|netease|qq|weibo|wx)/web|baijia|customize|netease|qq|weibo|wx))^ /api/web$uri break;
		rewrite (?!^/baijia/web)^/baijia(/.+)$ /baijia/web$1 break;
		rewrite (?!^/customize/web)^/customize(/.+)$ /customize/web$1 break;
        rewrite (?!^/netease/web)^/netease(/.+)$ /netease/web$1 break;
		rewrite (?!^/qq/web)^/qq(/.+)$ /qq/web$1 break;
		rewrite (?!^/weibo/web)^/weibo(/.+)$ /weibo/web$1 break;
		rewrite (?!^/wx/web)^/wx(/.+)$ /wx/web$1 break;

		include fastcgi_params;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		fastcgi_pass 127.0.0.1:9000;
		#fastcgi_pass unix:/var/run/php5-fpm.sock;
        try_files $fastcgi_script_name =404;
    }

    location ~ /\. {
        deny all;
    }
}

## LOCALHOST API ##
server {
    charset utf-8;

	client_max_body_size 200m;
	client_body_buffer_size 1024k;

	fastcgi_read_timeout 180s;

    listen 81; ## listen for ipv4
    #listen [::]:80 default_server ipv6only=on; ## listen for ipv6

    server_name localhost;

    root E:/wwwroot/channel-pub-api-feature-task-group;
    index index.php;

    access_log  logs/localhost.access.log;
    error_log   logs/localhost.error.log;

	location / {
        root E:/wwwroot/channel-pub-api-feature-task-group/api/web;
        try_files $uri $uri/ /api/web/index.php$is_args$args;

        # omit static files logging, and if they don't exist, avoid processing by Yii (uncomment if necessary)
        #location ~ ^/.+\.(css|js|ico|png|jpe?g|gif|svg|ttf|mp4|mov|swf|pdf|zip|rar)$ {
        #    log_not_found off;
        #    access_log off;
        #    try_files $uri =404;
        #}

        location ~ ^/assets/.+\.php(/|$) {
            deny all;
        }
    }

    location /baijia {
        alias E:/wwwroot/channel-pub-api-feature-task-group/baijia/web/;

        # redirect to the URL without a trailing slash (uncomment if necessary)
        #location = /baijia/ {
        #    return 301 /baijia;
        #}

        # prevent the directory redirect to the URL with a trailing slash
        location = /baijia {
            # if your location is "/baijia", try use "/baijia/baijia/web/index.php$is_args$args"
            # bug ticket: https://trac.nginx.org/nginx/ticket/97
            try_files $uri /baijia/baijia/web/index.php$is_args$args;
        }

        # if your location is "/baijia", try use "/baijia/baijia/web/index.php$is_args$args"
        # bug ticket: https://trac.nginx.org/nginx/ticket/97
        try_files $uri $uri/ /baijia/baijia/web/index.php$is_args$args;

        # omit static files logging, and if they don't exist, avoid processing by Yii (uncomment if necessary)
        #location ~ ^/baijia/.+\.(css|js|ico|png|jpe?g|gif|svg|ttf|mp4|mov|swf|pdf|zip|rar)$ {
        #    log_not_found off;
        #    access_log off;
        #    try_files $uri =404;
        #}

        location ~ ^/baijia/assets/.+\.php(/|$) {
            deny all;
        }
    }

	location /customize {
        alias E:/wwwroot/channel-pub-api-feature-task-group/customize/web/;

        # redirect to the URL without a trailing slash (uncomment if necessary)
        #location = /customize/ {
        #    return 301 /customize;
        #}

        # prevent the directory redirect to the URL with a trailing slash
        location = /customize {
            # if your location is "/customize", try use "/customize/customize/web/index.php$is_args$args"
            # bug ticket: https://trac.nginx.org/nginx/ticket/97
            try_files $uri /customize/customize/web/index.php$is_args$args;
        }

        # if your location is "/customize", try use "/customize/customize/web/index.php$is_args$args"
        # bug ticket: https://trac.nginx.org/nginx/ticket/97
        try_files $uri $uri/ /customize/customize/web/index.php$is_args$args;

        # omit static files logging, and if they don't exist, avoid processing by Yii (uncomment if necessary)
        #location ~ ^/customize/.+\.(css|js|ico|png|jpe?g|gif|svg|ttf|mp4|mov|swf|pdf|zip|rar)$ {
        #    log_not_found off;
        #    access_log off;
        #    try_files $uri =404;
        #}

        location ~ ^/customize/assets/.+\.php(/|$) {
            deny all;
        }
    }

	location /netease {
        alias E:/wwwroot/channel-pub-api-feature-task-group/netease/web/;

        # redirect to the URL without a trailing slash (uncomment if necessary)
        #location = /netease/ {
        #    return 301 /netease;
        #}

        # prevent the directory redirect to the URL with a trailing slash
        location = /netease {
            # if your location is "/netease", try use "/netease/netease/web/index.php$is_args$args"
            # bug ticket: https://trac.nginx.org/nginx/ticket/97
            try_files $uri /netease/netease/web/index.php$is_args$args;
        }

        # if your location is "/netease", try use "/netease/netease/web/index.php$is_args$args"
        # bug ticket: https://trac.nginx.org/nginx/ticket/97
        try_files $uri $uri/ /netease/netease/web/index.php$is_args$args;

        # omit static files logging, and if they don't exist, avoid processing by Yii (uncomment if necessary)
        #location ~ ^/netease/.+\.(css|js|ico|png|jpe?g|gif|svg|ttf|mp4|mov|swf|pdf|zip|rar)$ {
        #    log_not_found off;
        #    access_log off;
        #    try_files $uri =404;
        #}

        location ~ ^/netease/assets/.+\.php(/|$) {
            deny all;
        }
    }

    location /qq {
        alias E:/wwwroot/channel-pub-api-feature-task-group/qq/web/;

        # redirect to the URL without a trailing slash (uncomment if necessary)
        #location = /qq/ {
        #    return 301 /qq;
        #}

        # prevent the directory redirect to the URL with a trailing slash
        location = /qq {
            # if your location is "/qq", try use "/qq/qq/web/index.php$is_args$args"
            # bug ticket: https://trac.nginx.org/nginx/ticket/97
            try_files $uri /qq/qq/web/index.php$is_args$args;
        }

        # if your location is "/qq", try use "/qq/qq/web/index.php$is_args$args"
        # bug ticket: https://trac.nginx.org/nginx/ticket/97
        try_files $uri $uri/ /qq/qq/web/index.php$is_args$args;

        # omit static files logging, and if they don't exist, avoid processing by Yii (uncomment if necessary)
        #location ~ ^/qq/.+\.(css|js|ico|png|jpe?g|gif|svg|ttf|mp4|mov|swf|pdf|zip|rar)$ {
        #    log_not_found off;
        #    access_log off;
        #    try_files $uri =404;
        #}

        location ~ ^/qq/assets/.+\.php(/|$) {
            deny all;
        }
    }

	location /weibo {
        alias E:/wwwroot/channel-pub-api-feature-task-group/weibo/web/;

        # redirect to the URL without a trailing slash (uncomment if necessary)
        #location = /weibo/ {
        #    return 301 /weibo;
        #}

        # prevent the directory redirect to the URL with a trailing slash
        location = /weibo {
            # if your location is "/weibo", try use "/weibo/weibo/web/index.php$is_args$args"
            # bug ticket: https://trac.nginx.org/nginx/ticket/97
            try_files $uri /weibo/weibo/web/index.php$is_args$args;
        }

        # if your location is "/weibo", try use "/weibo/weibo/web/index.php$is_args$args"
        # bug ticket: https://trac.nginx.org/nginx/ticket/97
        try_files $uri $uri/ /weibo/weibo/web/index.php$is_args$args;

        # omit static files logging, and if they don't exist, avoid processing by Yii (uncomment if necessary)
        #location ~ ^/weibo/.+\.(css|js|ico|png|jpe?g|gif|svg|ttf|mp4|mov|swf|pdf|zip|rar)$ {
        #    log_not_found off;
        #    access_log off;
        #    try_files $uri =404;
        #}

        location ~ ^/weibo/assets/.+\.php(/|$) {
            deny all;
        }
    }

	location /wx {
        alias E:/wwwroot/channel-pub-api-feature-task-group/wx/web/;

        # redirect to the URL without a trailing slash (uncomment if necessary)
        #location = /wx/ {
        #    return 301 /wx;
        #}

        # prevent the directory redirect to the URL with a trailing slash
        location = /wx {
            # if your location is "/wx", try use "/wx/wx/web/index.php$is_args$args"
            # bug ticket: https://trac.nginx.org/nginx/ticket/97
            try_files $uri /wx/wx/web/index.php$is_args$args;
        }

        # if your location is "/wx", try use "/wx/wx/web/index.php$is_args$args"
        # bug ticket: https://trac.nginx.org/nginx/ticket/97
        try_files $uri $uri/ /wx/wx/web/index.php$is_args$args;

        # omit static files logging, and if they don't exist, avoid processing by Yii (uncomment if necessary)
        #location ~ ^/wx/.+\.(css|js|ico|png|jpe?g|gif|svg|ttf|mp4|mov|swf|pdf|zip|rar)$ {
        #    log_not_found off;
        #    access_log off;
        #    try_files $uri =404;
        #}

        location ~ ^/wx/assets/.+\.php(/|$) {
            deny all;
        }
    }

	location ~ ^/.+\.php(/|$) {
        rewrite (?!^/((api|baijia|customize|netease|qq|weibo|wx)/web|baijia|customize|netease|qq|weibo|wx))^ /api/web$uri break;
		rewrite (?!^/baijia/web)^/baijia(/.+)$ /baijia/web$1 break;
		rewrite (?!^/customize/web)^/customize(/.+)$ /customize/web$1 break;
        rewrite (?!^/netease/web)^/netease(/.+)$ /netease/web$1 break;
		rewrite (?!^/qq/web)^/qq(/.+)$ /qq/web$1 break;
		rewrite (?!^/weibo/web)^/weibo(/.+)$ /weibo/web$1 break;
		rewrite (?!^/wx/web)^/wx(/.+)$ /wx/web$1 break;

		include fastcgi_params;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		fastcgi_pass 127.0.0.1:9001;
		#fastcgi_pass unix:/var/run/php5-fpm.sock;
        try_files $fastcgi_script_name =404;
    }

    location ~ /\. {
        deny all;
    }
}

## MISC ##

### WWW Redirect ###
server {
    listen       80;
    server_name  channel-pub-api.localhost;
    return       301 http://www.channel-pub-api.localhost$request_uri;
}


3. Open a new PowerShell window and execute php-cgi.exe -b 127.0.0.1:9001-c C:/php-7.2.14/php.ini, as shown in Figure 4

Open a new PowerShell window and execute php-cgi.exe -b 127.0.0.1:9001-c C:/php-7.2.14/php.ini
Figure 4

4. Behavior of Nginx + php-fpm on Windows 10: when CURLing another request (http://localhost:81) from within a request (http://api.channel-pub-api.localhost), the response is successful, as shown in Figure 5

Behavior of Nginx + php-fpm on Windows 10: when CURLing another request (http://localhost:81) from within a request (http://api.channel-pub-api.localhost), the response is successful
Figure 5

5. Checking the specific request initiation timestamps, although these are parallel requests, they actually execute serially. That is, the next request starts only after the previous one finishes. The overall response time is 21.75s. See Figure 6

Checking the specific request initiation timestamps, although these are parallel requests, they actually execute serially. That is, the next request starts only after the previous one finishes. The overall response time is 21.75s.
Figure 6
Plaintext

10:37:26.340	info	yii\httpclient\StreamTransport::send	POST http://localhost:81/baijia/v1/articles/standard?group_id=015ce30b116ce86058fa6ab4fea4ac62
Content-Type: application/json; charset=UTF-8

10:37:29.461	info	yii\httpclient\StreamTransport::send	POST http://localhost:81/netease/v1/articles/standard?group_id=015ce30b116ce86058fa6ab4fea4ac62
Content-Type: application/json; charset=UTF-8

10:37:32.732	info	yii\httpclient\StreamTransport::send	POST http://localhost:81/weibo/v1/articles/toutiao?group_id=015ce30b116ce86058fa6ab4fea4ac62
Content-Type: application/json; charset=UTF-8

10:37:35.757	info	yii\httpclient\StreamTransport::send	POST http://localhost:81/qq/v1/articles/standard?group_id=015ce30b116ce86058fa6ab4fea4ac62
Content-Type: application/json; charset=UTF-8

10:37:38.533	info	yii\httpclient\StreamTransport::send	POST http://localhost:81/qq/v1/articles/standard?group_id=015ce30b116ce86058fa6ab4fea4ac62
Content-Type: application/json; charset=UTF-8

10:37:41.132	info	yii\httpclient\StreamTransport::send	POST http://localhost:81/wx/v1/wx-articles/article?group_id=015ce30b116ce86058fa6ab4fea4ac62
Content-Type: application/json; charset=UTF-8

10:37:44.207	info	yii\httpclient\StreamTransport::send	POST http://localhost:81/customize/v1/articles/standard?group_id=015ce30b116ce86058fa6ab4fea4ac62
Content-Type: application/json; charset=UTF-8

6. I decided to analyze and test the serial behavior of Nginx + php-fpm on Windows 10. I created phpinfo.php (writes to log with a 30-second delay) and phpinfo1.php (writes to log with a 5-second delay), then opened phpinfo.php in the browser followed quickly by phpinfo1.php, with an interval of about 1 second.
phpinfo.php

PHP
<?php
sleep(30);
file_put_contents('E:/wwwroot/channel-pub-api/console/runtime/logs/sleep-0-' . time() . '.txt', time());
phpinfo();
?>

phpinfo1.php

PHP
<?php
sleep(5);
file_put_contents('E:/wwwroot/channel-pub-api/console/runtime/logs/sleep-1-' . time() . '.txt', time());
phpinfo();
?>

7. After opening phpinfo.php, it took about 30 seconds to load. After opening phpinfo1.php, it took about 35 seconds to load (if parallel processing were supported, the load time would be expected to be about 5 seconds. If parallel processing is not supported and only serial processing is, the load time would be expected to be about 35 seconds: 30 seconds waiting for phpinfo.php to finish running, since port 9001 only becomes available after phpinfo.php finishes, and 5 seconds for phpinfo1.php’s own execution). See Figure 7

After opening phpinfo.php, it took about 30 seconds to load. After opening phpinfo1.php, it took about 35 seconds to load (if parallel processing were supported, the load time would be expected to be about 5 seconds. If parallel processing is not supported and only serial processing is, the load time would be expected to be about 35 seconds: 30 seconds waiting for phpinfo.php to finish running, since port 9001 only becomes available after phpinfo.php finishes, and 5 seconds for phpinfo1.php's own execution).
Figure 7

8. Check the creation times of the generated log files respectively. It can be determined that the creation time of the phpinfo1.php log file is later than that of the phpinfo.php log file, by exactly 5 seconds. This confirms that Nginx + php-fpm on Windows 10 only supports serial requests. See Figure 8

Check the creation times of the generated log files respectively. It can be determined that the creation time of the phpinfo1.php log file is later than that of the phpinfo.php log file, by exactly 5 seconds. This confirms that Nginx + php-fpm on Windows 10 only supports serial requests.
Figure 8
Plaintext

sleep-0-1585200354.txt
sleep-1-1585200359.txt

9. The development environment deployment plan is: CentOS + Nginx + php-fpm. Repeat steps 6, 7, and 8. Check the creation times of the generated log files respectively. It can be determined that the creation time of the phpinfo1.php log file is earlier than that of the phpinfo.php log file, by exactly 23 seconds, even though it started running later than phpinfo.php. This confirms that Nginx + php-fpm on CentOS 7 supports parallel requests. See Figure 9

The development environment deployment plan is: CentOS + Nginx + php-fpm. Repeat steps 6, 7, and 8. Check the creation times of the generated log files respectively. It can be determined that the creation time of the phpinfo1.php log file is earlier than that of the phpinfo.php log file, by exactly 23 seconds, even though it started running later than phpinfo.php. This confirms that Nginx + php-fpm on CentOS 7 supports parallel requests.
Figure 9
Plaintext

sleep-0-1585202045.txt
sleep-1-1585202022.txt

10. Edit the Nginx configuration file and modify the server_name value to: api.channel-pub.wjdev.chinamcloud.cn localhost, so that CURLing another request (http://localhost) from within a request (https://api.channel-pub.wjdev.chinamcloud.cn) (7 requests in total) directly targets the local machine, saving network overhead. The overall response time is 1956ms, about 2 seconds, which meets expectations. See Figure 10

Edit the Nginx configuration file and modify the server_name value to: api.channel-pub.wjdev.chinamcloud.cn localhost, so that CURLing another request (http://localhost) from within a request (https://api.channel-pub.wjdev.chinamcloud.cn) (7 requests in total) directly targets the local machine, saving network overhead. The overall response time is 1956ms, about 2 seconds, which meets expectations.
Figure 10

11. When making requests directly to the local machine, the number of concurrent requests is limited by the pm.max_children value in php-fpm.conf. It is currently set to the default: 40. The number of child processes is fixed at 40. When CURLing another request (http://localhost) from within a request (https://api.channel-pub.wjdev.chinamcloud.cn) 52 times, the overall response time is 6.00s. See Figure 11

When making requests directly to the local machine, the number of concurrent requests is limited by the pm.max_children value in php-fpm.conf. It is currently set to the default: 40. The number of child processes is fixed at 40. When CURLing another request (http://localhost) from within a request (https://api.channel-pub.wjdev.chinamcloud.cn) 52 times, the overall response time is 6.00s.
Figure 11

12. When the number of requests is 42, the overall response time is 4.73s. When the number of requests is 35, the overall response time is 4.39s. When the number of requests is 30, the overall response time is 3.79s. When the number of requests is 25, the overall response time is 2.98s. When the number of requests is 20, the overall response time is 2.85s. When the number of requests is 15, the overall response time is 2.36s. When the number of requests is 10, the overall response time is 2.21s.

13. Run curl on the server to view the php-fpm status page.

Plaintext

[root@5b9088596e62 /]# curl http://127.0.0.1/status
pool:                 www
process manager:      static
start time:           26/Mar/2020:13:50:05 +0800
start since:          4603
accepted conn:        516
listen queue:         0
max listen queue:     0
listen queue len:     128
idle processes:       39
active processes:     1
total processes:      40
max active processes: 10
max children reached: 0
slow requests:        0

14. Final analysis and test results: Windows + Nginx + php-fpm (serial), CentOS + Nginx + php-fpm (parallel), MacOS + Nginx + php-fpm (parallel), MacOS + Apache (parallel).

关于作者 · 持续学习与技术实践

我是一名拥有 15 年以上开发经验的技术从业者,自 2013 年起持续运营个人技术博客,记录工作与个人项目中遇到的真实问题,以及解决问题过程中的探索、实践和思考。

除了技术写作,我也在持续开发和维护自己的独立项目,探索新技术和新工具在实际场景中的应用。我始终相信,没有不值得去解决的问题,也没有不值得去学习的技术。

如果这篇文章对你有所帮助,欢迎浏览博客中的其他文章,也欢迎交流技术经验与想法。

关于我  ·  GitHub  ·  邮件联系