You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PHP与C# HttpClient并行请求后出现400错误的排查求助

XML转PDF项目并发请求400错误排查与解决

我正在开发一个XML转PDF的项目,通过C#应用向PHP服务器发送HTTP POST请求。前期一切正常,但处理约100个并发请求后,服务器开始返回400 Bad Request错误。调整过客户端和服务器相关设置,问题仍未解决,需要排查原因和解决方法。


C#客户端代码

private async Task SendRequest(string xmlKey, string diretorioPdf, string contentXml)
{
    client.DefaultRequestHeaders.Add("xmlKey", xmlKey);
    client.DefaultRequestHeaders.Add("diretorioPdf", diretorioPdf);

    var content = new StringContent($"{{\"content\":\"{Convert.ToBase64String(Encoding.UTF8.GetBytes(contentXml))}\"}}", Encoding.UTF8, "application/json");

    var response = await client.PostAsync("http://localhost:3000/conversao.php", content);
    response.EnsureSuccessStatusCode();
}

PHP服务器代码

服务器会解码Base64内容并处理XML,验证必填请求头后生成PDF文件。

$headers = getallheaders();
if (!isset($headers['xmlKey']) || !isset($headers['diretorioPdf'])) {
    header('Content-Type: application/json');
    echo json_encode(["status" => "Missing headers"]);
    exit();
}

$jsonData = file_get_contents('php://input');
$data = json_decode($jsonData, true);

if (!isset($data['content'])) {
    echo "Missing 'content' field.";
    exit();
}

$xml = base64_decode($data['content']);
// 处理XML并生成PDF...

已尝试的解决操作

  • 降低C#客户端并发阈值:
    private readonly SemaphoreSlim semaphore = new SemaphoreSlim(10); // 最大10线程
    
  • 发送前验证数据:在C#代码中添加验证,确保请求头和XML内容正确。

错误信息

程序运行后,前78个XML文件转换成功,随后出现以下错误:

The response status code does not indicate success: 400 (Bad Request).
    in System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
    in Cocal.Src.Xml.TransformarEmPDF.ConversorPDF.<SendRequest>d__19.MoveNext() in C:\Users\sserg\source\repos\Cocal\Cocal\Src\Xml\TransformarEmPDF\ConversorPDF.cs:linha 155
--- End stack trace of the previous location where the exception was thrown ---
    in System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    in System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    in System.Runtime.CompilerServices.TaskAwaiter.GetResult()
    in Cocal.Src.Xml.TransformarEmPDF.ConversorPDF.<ProcessRequest>d__18.MoveNext() in C:\Users\sserg\source\repos\Cocal\Cocal\Src\Xml\TransformarEmPDF\ConversorPDF.cs:linha 123
    in System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
    in Cocal.Src.Xml.TransformarEmPDF.ConversorPDF.<SendRequest>d__19.MoveNext() na C:\Users\sserg\source\repos\Cocal\Coc

Apache错误日志(C:\xampp\apache\logs\error.log)

[Mon Dec 09 16:52:23.643126 2024] [ssl:warn] [pid 10384:tid 612] AH01909: www.example.com:443:0 server certificate does NOT include an ID which matches the server name
[Mon Dec 09 16:52:23.769786 2024] [core:warn] [pid 10384:tid 612] AH00098: pid file C:/xampp/apache/logs/httpd.pid overwritten -- Unclean shutdown of previous Apache run?
[Mon Dec 09 16:52:23.773776 2024] [ssl:warn] [pid 10384:tid 612] AH01909: www.example.com:443:0 server certificate does NOT include an ID which matches the server name
[Mon Dec 09 16:52:24.651449 2024] [mpm_winnt:notice] [pid 10384:tid 612] AH00455: Apache/2.4.58 (Win64) OpenSSL/3.1.3 PHP/8.2.12 configured -- resuming normal operations
[Mon Dec 09 16:52:24.651449 2024] [mpm_winnt:notice] [pid 10384:tid 612] AH00456: Apache Lounge VS17 Server built: Oct 18 2023 13:03:18
[Mon Dec 09 16:52:24.651449 2024] [core:notice] [pid 10384:tid 612] AH00094: Command line: 'c:\\xampp\\apache\\bin\\httpd.exe -d C:/xampp/apache'
[Mon Dec 09 16:52:24.657432 2024] [mpm_winnt:notice] [pid 10384:tid 612] AH00418: Parent: Created child process 33444
[Mon Dec 09 16:52:25.432362 2024] [ssl:warn] [pid 33444:tid 632] AH01909: www.example.com:443:0 server certificate does NOT include an ID which matches the server name
[Mon Dec 09 16:52:25.534090 2024] [ssl:warn] [pid 33444:tid 632] AH01909: www.example.com:443:0 server certificate does NOT include an ID which matches the server name
[Mon Dec 09 16:52:25.646789 2024] [mpm_winnt:notice] [pid 33444:tid 632] AH00354: Child: Starting 150 worker threads.
[Wed Dec 11 23:26:10.601035 2024] [ssl:warn] [pid 26360:tid 600] AH01909: www.example.com:443:0 server certificate does NOT include an ID which matches the server name
[Wed Dec 11 23:26:10.688648 2024] [core:warn] [pid 26360:tid 600] AH00098: pid file C:/xampp/apache/logs/httpd.pid overwritten -- Unclean shutdown of previous Apache run?
[Wed Dec 11 23:26:10.693636 2024] [ssl:warn] [pid 26360:tid 600] AH01909: www.example.com:443:0 server certificate does NOT include an ID which matches the server name
[Wed Dec 11 23:26:11.366501 2024] [mpm_winnt:notice] [pid 26360:tid 600] AH00455: Apache/2.4.58 (Win64) OpenSSL/3.1.3 PHP/8.2.12 configured -- resuming normal operations
[Wed Dec 11 23:26:11.366501 2024] [mpm_winnt:notice] [pid 26360:tid 600] AH00456: Apache Lounge VS17 Server built: Oct 18 2023 13:03:18
[Wed Dec 11 23:26:11.366501 2024] [core:notice] [pid 26360:tid 600] AH00094: Command line: 'c:\\xampp\\apache\\bin\\httpd.exe -d C:/xampp/apache'
[Wed Dec 11 23:26:11.371489 2024] [mpm_winnt:notice] [pid 26360:tid 600] AH00418: Parent: Created child process 26504
[Wed Dec 11 23:26:12.029726 2024] [ssl:warn] [pid 26504:tid 604] AH01909: www.example.com:443:0 server certificate does NOT include an ID which matches the server name
[Wed Dec 11 23:26:12.109550 2024] [ssl:warn] [pid 26504:tid 604] AH01909: www.example.com:443:0 server certificate does NOT include an ID which matches the server name
[Wed Dec 11 23:26:12.173341 2024] [mpm_winnt:notice] [pid 26504:tid 604] AH00354: Child: Starting 150 worker threads.

PHP版本

PHP 8.2.12 (cli) (built: Oct 24 2023 21:15:15) (ZTS Visual C++ 2019 x64)
Copyright (c) The PHP Group
Zend Engine v4.2.12, Copyright (c) Zend Technologies

问题排查与解决思路

1. C#客户端核心问题:请求头重复添加

你的client应该是全局实例,每次调用SendRequest时执行client.DefaultRequestHeaders.Add会导致请求头被重复添加(比如同一个xmlKey头会出现多次),当请求积累到一定数量后,HTTP请求头格式非法,触发400错误。

修复方案:
不要直接在全局HttpClient的默认头里添加请求头,改为每次请求时创建独立的请求消息:

private async Task SendRequest(string xmlKey, string diretorioPdf, string contentXml)
{
    using var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost:3000/conversao.php");
    request.Headers.Add("xmlKey", xmlKey);
    request.Headers.Add("diretorioPdf", diretorioPdf);

    // 用JsonContent自动序列化,避免手动拼接JSON的格式错误
    var jsonBody = new { content = Convert.ToBase64String(Encoding.UTF8.GetBytes(contentXml)) };
    request.Content = JsonContent.Create(jsonBody);

    var response = await client.SendAsync(request);
    response.EnsureSuccessStatusCode();
}

2. 手动拼接JSON的潜在风险

手动拼接JSON字符串时,若Base64编码内容出现特殊字符(虽然Base64不会有,但编码逻辑变更后可能出现),会导致JSON格式错误,触发400。使用JsonContent或Newtonsoft.Json序列化能确保JSON格式合法。

3. PHP服务器添加请求日志

当前Apache日志未记录请求级错误,建议在PHP代码中添加日志,精准定位触发400的请求细节:

// 自定义日志文件路径
$logFile = __DIR__ . '/request_errors.log';

// 记录请求时间和基本信息
error_log(date('[Y-m-d H:i:s] ') . "New request received\n", 3, $logFile);
// 记录请求头
error_log(date('[Y-m-d H:i:s] ') . "Headers: " . print_r(getallheaders(), true) . "\n", 3, $logFile);

$headers = getallheaders();
if (!isset($headers['xmlKey']) || !isset($headers['diretorioPdf'])) {
    error_log(date('[Y-m-d H:i:s] ') . "ERROR: Missing required headers\n", 3, $logFile);
    header('HTTP/1.1 400 Bad Request');
    echo json_encode(["status" => "Missing headers"]);
    exit();
}

$jsonData = file_get_contents('php://input');
error_log(date('[Y-m-d H:i:s] ') . "Request body: " . $jsonData . "\n", 3, $logFile);

$data = json_decode($jsonData, true);
if (json_last_error() !== JSON_ERROR_NONE) {
    error_log(date('[Y-m-d H:i:s] ') . "ERROR: JSON decode failed - " . json_last_error_msg() . "\n", 3, $logFile);
    header('HTTP/1.1 400 Bad Request');
    echo json_encode(["status" => "Invalid JSON"]);
    exit();
}

if (!isset($data['content'])) {
    error_log(date('[Y-m-d H:i:s] ') . "ERROR: Missing 'content' field\n", 3, $logFile);
    header('HTTP/1.1 400 Bad Request');
    echo json_encode(["status" => "Missing 'content' field"]);
    exit();
}

$xml = base64_decode($data['content']);
// 处理XML并生成PDF...

4. 调整Apache并发参数

Apache的mpm_winnt模块默认连接队列可能不足,导致高并发下请求被拒绝。修改httpd.conf中的MPM配置:

<IfModule mpm_winnt_module>
    ThreadsPerChild        150
    MaxConnectionsPerChild   0
    ListenBacklog           512  # 增大队列长度
</IfModule>

内容的提问来源于stack exchange,提问作者Luz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 14:23:09