AsyncFastCGI.NET
用C#编写的.NET Core的完全异步FastCGI客户库库。用于开发Web应用程序的非侵入性替代方案。
所有零件均根据Nginx使用的FastCGI规范实现。请参阅本文档的结尾,以示例NGINX配置。当使用NGINX中的KeepAlive设置进行FastCGI连接时,性能在高负载下是稳定的。
安装
该库可在Nuget上找到。
dotnet add package AsyncFastCGI.NET
例子
在处理参数(包括HTTP标头)之后,请调用您的请求处理程序方法,但在读取请求有效负载之前。
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 ( ) ; } /// <summary> /// Here comes your code to handle requests. /// </summary> 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 ( $@ \"<!DOCTYPE html> <html> <body> <h1>Hello World!</h1> <p><b>Request URI:</b> { requestURI } </p> <p><b>Request Method:</b> { requestMethod } </p> <p><b>Remote Address:</b> { remoteAddress } </p> <p> <form method=\'post\'> <input type=\'text\' name=\'data\' length=\'60\'> <input type=\'submit\' value=\'Submit\'> </form> </p> <p><b>Posted data:</b></p> <pre> { requestData } </pre> </body> </html> \" ) ; 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。
构建和运行
-
在Ubuntu上安装
.NET Core18.04- https://docs.mi*cr*os*oft.com/en-us/dotnet/core/install/linux-ubuntu
-
建造或运行进行调试和开发
dotnet build dotnet run 8080
-
释放构建
对于Ubuntu和Windows:
dotnet publish -c Release -r ubuntu.18.04-x64 dotnet publish -c Release -r win10-x64
-
创建发布包
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;
}
}
