一、基础 http 请求方法
1. httpclient 基础用法
// get 请求示例
async task<string> getdataasync(string url)
{
using var httpclient = new httpclient();
httpresponsemessage response = await httpclient.getasync(url);
response.ensuresuccessstatuscode();
return await response.content.readasstringasync();
}
// post 请求示例
async task postdataasync(string url, object data)
{
using var httpclient = new httpclient();
var json = jsonserializer.serialize(data);
var content = new stringcontent(json, encoding.utf8, "application/json");
var response = await httpclient.postasync(url, content);
response.ensuresuccessstatuscode();
}警告:不要每次请求创建新 httpclient!这会导致:
- 端口耗尽 (time_wait 状态)
- dns 更新延迟
- 连接池无法复用
二、高性能 http 客户端实践
1. ihttpclientfactory 最佳实践
// 1. startup 注册服务
services.addhttpclient("financeapi", client => {
client.baseaddress = new uri("https://api.finance.com");
client.timeout = timespan.fromseconds(15);
client.defaultrequestheaders.add("accept", "application/json");
});
// 2. 控制器中使用
public class datacontroller : controller
{
private readonly ihttpclientfactory _factory;
public datacontroller(ihttpclientfactory factory) => _factory = factory;
public async task<iactionresult> getstockdata()
{
var client = _factory.createclient("financeapi");
var response = await client.getasync("/stocks/msft");
// ...
}
}2. http/2 连接复用
var handler = new socketshttphandler
{
pooledconnectionlifetime = timespan.fromminutes(5),
enablemultiplehttp2connections = true
};
var client = new httpclient(handler)
{
defaultrequestversion = httpversion.version20,
defaultversionpolicy = httpversionpolicy.requestversionexact
};3. 流式处理大响应
// 避免大响应阻塞内存
async task processlargeresponse(string url)
{
using var client = new httpclient();
using var response = await client.getasync(url, httpcompletionoption.responseheadersread);
using var stream = await response.content.readasstreamasync();
await using var buffer = new bufferedstream(stream);
using var reader = new streamreader(buffer);
while (!reader.endofstream)
{
var line = await reader.readlineasync();
processline(line); // 逐行处理
}
}三、高级场景实现
1. 自定义重试策略
// 指数退避重试器
async task<t> executewithretry<t>(func<task<t>> action, int maxretries = 3)
{
int retrycount = 0;
while (true)
{
try
{
return await action();
}
catch (httprequestexception ex) when (ex.statuscode == httpstatuscode.toomanyrequests)
{
if (retrycount++ >= maxretries) throw;
var delay = timespan.fromseconds(math.pow(2, retrycount));
await task.delay(delay);
}
}
}
// 使用示例
var data = await executewithretry(() => getdataasync("https://unstable-api.com/data"));2. 动态请求头签名
// 安全 api 调用签名
async task sendsignedrequest(string url)
{
var handler = new customsignaturehandler();
var client = new httpclient(handler);
// ... 正常调用
}
class customsignaturehandler : delegatinghandler
{
protected override async task<httpresponsemessage> sendasync(
httprequestmessage request,
cancellationtoken canceltoken)
{
// 1. 获取时间戳
var timestamp = datetimeoffset.utcnow.tounixtimemilliseconds();
// 2. 生成签名
var signdata = $"{request.method}{request.requesturi}{timestamp}{api_secret}";
var signature = hmacsha256.hash(signdata);
// 3. 添加安全头
request.headers.add("x-timestamp", timestamp.tostring());
request.headers.add("x-signature", convert.tobase64string(signature));
return await base.sendasync(request, canceltoken);
}
}四、性能优化策略
1. 连接管理优化
| 参数 | 推荐值 | 作用 |
|---|---|---|
| maxconnectionsperserver | 50-100 | 控制单个主机最大连接数 |
| pooledconnectionidletimeout | 1-2 分钟 | 空闲连接保持时间 |
| pooledconnectionlifetime | 5-10 分钟 | 连接最大存活时间 |
2. 响应处理优化技巧
// 高效 json 反序列化
async task<t> parsejsonresponse<t>(httpresponsemessage response)
{
// 使用流式 api 避免大对象分配
await using var stream = await response.content.readasstreamasync();
return await jsonserializer.deserializeasync<t>(stream, new jsonserializeroptions
{
propertynamecaseinsensitive = true,
defaultbuffersize = 8192 // 8kb 缓冲区
});
}
// 使用 arraypool 处理二进制响应
async task processbinaryresponse(string url)
{
var response = await _httpclient.getasync(url);
var buffer = arraypool<byte>.shared.rent(1024 * 64);
try
{
await using var stream = await response.content.readasstreamasync();
int bytesread;
while ((bytesread = await stream.readasync(buffer)) > 0)
{
processchunk(new readonlyspan<byte>(buffer, 0, bytesread));
}
}
finally
{
arraypool<byte>.shared.return(buffer);
}
}五、常见问题解决方案
1. dns 更新问题
// 强制刷新 dns 缓存
var handler = new socketshttphandler
{
pooledconnectionlifetime = timespan.fromminutes(5), // 设置连接生命周期
pooledconnectionidletimeout = timespan.fromseconds(30)
};2. 证书验证处理
// 开发环境忽略证书错误(生产环境禁用!)
var handler = new httpclienthandler
{
servercertificatecustomvalidationcallback = (_, _, _, _) => true
};3. 多部分表单上传
async task uploadfile(string url, string filepath)
{
using var content = new multipartformdatacontent();
using var filestream = file.openread(filepath);
content.add(new streamcontent(filestream), "file", "data.zip");
content.add(new stringcontent("2024-report"), "description");
var response = await _httpclient.postasync(url, content);
response.ensuresuccessstatuscode();
}六、性能监控与诊断
1. httpclient 指标监控
# 查看连接池状态 dotnet-counters monitor -n myapp system.net.http
2. 请求跟踪
// 添加日志记录器
services.addhttpclient("loggingclient")
.configureprimaryhttpmessagehandler(() => new logginghandler(new socketshttphandler()));
class logginghandler : delegatinghandler
{
protected override async task<httpresponsemessage> sendasync(
httprequestmessage request, cancellationtoken cancellationtoken)
{
var stopwatch = stopwatch.startnew();
try
{
return await base.sendasync(request, cancellationtoken);
}
finally
{
_logger.loginformation($"{request.method} {request.requesturi} took {stopwatch.elapsedmilliseconds}ms");
}
}
}最佳实践总结:
- 连接管理:始终重用
httpclient,通过工厂管理生命周期 - 协议选择:启用 http/2 提升并发性能(尤其在高延迟网络)
- 资源控制:流式处理响应,避免大内存分配
- 弹性策略:实现重试/熔断机制(推荐使用 polly)
- 监控保障:持续跟踪请求延迟和错误率

性能对比:
| 场景 | 原始方式 | 优化方式 | 提升幅度 |
|---|---|---|---|
| 1000次连续请求 | 28秒 | 9.2秒 | 3倍 |
| 10mb json 响应 | 1.2秒 | 0.4秒 | 3倍 |
| 高并发连接 | 350 qps | 1200 qps | 3.4倍 |
以上就是c#实现http请求的多种方案的详细内容,更多关于c#实现http请求的资料请关注代码网其它相关文章!
发表评论