9人参与 • 2025-07-24 • Asp.net
// 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
!这会导致:
// 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"); // ... } }
var handler = new socketshttphandler { pooledconnectionlifetime = timespan.fromminutes(5), enablemultiplehttp2connections = true }; var client = new httpclient(handler) { defaultrequestversion = httpversion.version20, defaultversionpolicy = httpversionpolicy.requestversionexact };
// 避免大响应阻塞内存 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); // 逐行处理 } }
// 指数退避重试器 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"));
// 安全 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); } }
参数 | 推荐值 | 作用 |
---|---|---|
maxconnectionsperserver | 50-100 | 控制单个主机最大连接数 |
pooledconnectionidletimeout | 1-2 分钟 | 空闲连接保持时间 |
pooledconnectionlifetime | 5-10 分钟 | 连接最大存活时间 |
// 高效 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); } }
// 强制刷新 dns 缓存 var handler = new socketshttphandler { pooledconnectionlifetime = timespan.fromminutes(5), // 设置连接生命周期 pooledconnectionidletimeout = timespan.fromseconds(30) };
// 开发环境忽略证书错误(生产环境禁用!) var handler = new httpclienthandler { servercertificatecustomvalidationcallback = (_, _, _, _) => true };
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(); }
# 查看连接池状态 dotnet-counters monitor -n myapp system.net.http
// 添加日志记录器 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
,通过工厂管理生命周期性能对比:
场景 | 原始方式 | 优化方式 | 提升幅度 |
---|---|---|---|
1000次连续请求 | 28秒 | 9.2秒 | 3倍 |
10mb json 响应 | 1.2秒 | 0.4秒 | 3倍 |
高并发连接 | 350 qps | 1200 qps | 3.4倍 |
以上就是c#实现http请求的多种方案的详细内容,更多关于c#实现http请求的资料请关注代码网其它相关文章!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论