AsyncFastCGI.NET

其他类别 2025-08-19

AsyncFastCGI.NET

用C#编写的.NET Core的完全异步FastCGI客户库库。用于开发Web应用程序的非侵入性替代方案。

所有零件均根据Nginx使用的FastCGI规范实现。请参阅本文档的结尾,以示例NGINX配置。当使用NGINX中的KeepAlive设置进行FastCGI连接时,性能在高负载下是稳定的。

安装

该库可在Nuget上找到。

 dotnet add package AsyncFastCGI.NET

例子

在处理参数(包括HTTP标头)之后,请调用您的请求处理程序方法,但在读取请求有效负载之前。

/// Here comes your code to handle requests. /// private static async Task RequestHandler(AsyncFastCGI.Input input, AsyncFastCGI.Output output) { output.SetHttpStatus(200); output.SetHeader("Content-Type", "text/html; charset=utf-8"); string requestURI = input.GetParameter("REQUEST_URI"); string requestMethod = input.GetParameter("REQUEST_METHOD"); string remoteAddress = input.GetParameter("REMOTE_ADDR"); string requestData = WebUtility.HtmlEncode(await input.GetContentAsync()); await output.WriteAsync($@"

Hello World!

Request URI: {requestURI}

Request Method: {requestMethod}

Remote Address: {remoteAddress}

Posted data:

{requestData}
"); await output.EndAsync(); } }">
 class Program
{
    static async Task Main ( string [ ] args )
    {
        var client = new AsyncFastCGI . Client ( ) ;

        client . setPort ( 9090 ) ;
        client . setBindAddress ( "0.0.0.0" ) ;       // Bind to all interfaces
        client . setMaxConcurrentRequests ( 256 ) ;   // When reached then queued
        client . setConnectionTimeout ( 10000 ) ;     // 10 seconds
        client . SetMaxHeaderSize ( 16384 ) ;         // 16 KB. Max HTTP header length
        client . requestHandler = Program . requestHandler ;
        
        await client . startAsync ( ) ;
    }

    /// 
    /// Here comes your code to handle requests.
    /// 
    private static async Task RequestHandler ( AsyncFastCGI . Input input , AsyncFastCGI . Output output ) {
        output . SetHttpStatus ( 200 ) ;
        output . SetHeader ( "Content-Type" , "text/html; charset=utf-8" ) ;

        string requestURI = input . GetParameter ( "REQUEST_URI" ) ;
        string requestMethod = input . GetParameter ( "REQUEST_METHOD" ) ;
        string remoteAddress = input . GetParameter ( "REMOTE_ADDR" ) ;
        string requestData = WebUtility . HtmlEncode ( await input . GetContentAsync ( ) ) ;

        await output . WriteAsync ( $@ "

    
        

Hello World!

Request URI: { requestURI }

Request Method: { requestMethod }

Remote Address: { remoteAddress }

Posted data:

 { requestData } 
" ) ; await output . EndAsync ( ) ; } }

输出如下:

基准结果

基准测试是在另一个项目中完成的。有关更多信息,请参见FastCGI基础。以下结果示例是Nodejs客户端,此库和用C#编写的非Async库之间的高并发比较。

必须注意的是,所有FASTCGI客户端都需要在400之前进行较低并发的热身,否则第一个X连接失败了。

keepalive = on / confistrency = 400

尽管使用NGINX中的KeepAlive设置,短期性能会更糟,但这仍然是任何FastCGI库的唯一可持续方法。在运行Apachebench测试时可以看到原因大约5分钟。当禁用KeepAlive时,NGINX为其每个传入连接创建了与客户端的新TCP连接。二手端口的计数很快达到了最大65535,因为即使连接完成,它们的插座也保持了一段TIME_WAIT 。因此,最重要的用例是当keepalive = ON时,端口不会耗尽:

 ab -kc 400 -n 200000 127.0.0.1/PATH

NGINX设置:

 fastcgi_keep_conn on;
fastcgi_request_buffering off;
keepalive 400;

node-fastcgi库不支持keepalive设置。请求完成后,它立即关闭了TCP连接到NGINX。

图书馆 req。 /秒 req。时间 浓RT 最长的R. 失败的
AsyncFastCGI.NET 9111.87 43.899毫秒 0.110 ms 92毫秒 0
node-fastcgi 没有支持 没有支持 没有支持 没有支持 没有支持
lb fastcgi 失败 失败 失败 失败 失败

req。时间:平均|浓RT:平均在所有并发请求中

keepalive = off / prostrency = 400

如上几点所述,不建议在nginx中关闭Keepalive。此选项显示该选项的唯一原因是Nodejs库的工作原理,结果是可比的。

 ab -kc 400 -n 200000 127.0.0.1/PATH

NGINX设置:

 fastcgi_keep_conn off;
fastcgi_request_buffering off;
图书馆 req。 /秒 req。时间 浓RT 最长的R. 失败的
AsyncFastCGI.NET 19893.88 20.107毫秒 0.050 ms 2044 MS 0
node-fastcgi 21411.16 18.682 ms 0.047毫秒 1062毫秒 0
lb fastcgi 失败 失败 失败 失败 失败

req。时间:平均|浓RT:平均在所有并发请求中

LB FastCGI库可以处理的最大并发性约为50-60。

构建和运行

  1. 在Ubuntu上安装.NET Core 18.04

    • https://docs.mi*cr*os*oft.com/en-us/dotnet/core/install/linux-ubuntu
  2. 建造或运行进行调试和开发

    dotnet build
    dotnet run 8080
  3. 释放构建

    对于Ubuntu和Windows:

    dotnet publish -c Release -r ubuntu.18.04-x64
    
    dotnet publish -c Release -r win10-x64
  4. 创建发布包

    dotnet pack -c Release

nginx配置

使用least_conn负载平衡模式时,性能会更糟。

    upstream fastcgi_backend_csharp {
            keepalive 400;

            server 127.0.0.1:9090;
            server 127.0.0.1:9091;
            server 127.0.0.1:9092;
            server 127.0.0.1:9093;
    }

    server {
            listen 80 default_server;
            listen [::]:80 default_server;

            root /var/www/html;
            server_name _;

            fastcgi_keep_conn on;
            fastcgi_request_buffering off;

            location / {
                    try_files $uri $uri/ =404;
            }

            location /asyncfastcgi {
                    include /etc/nginx/fastcgi_params;
                    fastcgi_pass fastcgi_backend_csharp;
            }
    }
下载源码

通过命令行克隆项目:

git clone https://github.com/bolner/AsyncFastCGI.NET.git