net/http 库的客户端实现(下)

news/2024/5/15 9:14:59/文章来源:https://blog.csdn.net/upstream480/article/details/128429174

前言

上一篇文章我们讲了 net/http 库客户端 request 的构建,接下来继续讲构建HTTP请求之后的处理操作

net/http 库的客户端实现(上)

net/http 库的客户端实现(下)

net/http 库的服务端实现

启动事务

构建 HTTP 请求后,接着需要开启HTTP事务进行请求并且等待远程响应,以net/http.Client.Do()方法为例子,理一下它的调用链路:

  • net/http.Client.Do()
  • net/http.Client.do()
  • net/http.Client.send()
  • net/http.Send()
  • net/http.Transport.RoundTrip()

RoundTrip()RoundTripper类型中的一个的方法,net/http.Transport是其中的一个实现,可以在net/http/transport.go文件中找到这个方法,看一下源码。

func (t *Transport) roundTrip(req *Request) (*Response, error) {// 省略for {// 检测 ctx 退出信号select {case <-ctx.Done():req.closeBody()return nil, ctx.Err()default:}// 获取连接,通过使用连接池对资源进行了复用;pconn, err := t.getConn(treq, cm)if err != nil {t.setReqCanceler(cancelKey, nil)req.closeBody()return nil, err}var resp *Responseif pconn.alt != nil {// HTTP/2 path.t.setReqCanceler(cancelKey, nil) // not cancelable with CancelRequestresp, err = pconn.alt.RoundTrip(req)} else {// 处理响应resp, err = pconn.roundTrip(treq)}if err == nil {resp.Request = origReqreturn resp, nil}// Rewind the body if we're able to.req, err = rewindBody(req)if err != nil {return nil, err}}
}

重点看两部分

  • net/http.Transport.getConn()获取连接
  • net/http.persistConn.roundTrip()处理写入 HTTP 请求,并在select中等待响应的返回

获取连接(getConn)

func (t *Transport) getConn(treq *transportRequest, cm connectMethod) (pc *persistConn, err error) {req := treq.Requesttrace := treq.tracectx := req.Context()if trace != nil && trace.GetConn != nil {trace.GetConn(cm.addr())}w := &wantConn{cm:         cm,key:        cm.key(),ctx:        ctx,ready:      make(chan struct{}, 1),beforeDial: testHookPrePendingDial,afterDial:  testHookPostPendingDial,}defer func() {if err != nil {w.cancel(t, err)}}()// 在队列中有闲置连接,直接返回if delivered := t.queueForIdleConn(w); delivered {pc := w.pcreturn pc, nil}cancelc := make(chan error, 1)t.setReqCanceler(treq.cancelKey, func(err error) { cancelc <- err })// 放到队列中等待建立新的连接t.queueForDial(w)// 阻塞等待连接select {case <-w.ready:return w.pc, w.errcase <-req.Cancel:return nil, errRequestCanceledConncase <-req.Context().Done():return nil, req.Context().Err()case err := <-cancelc:if err == errRequestCanceled {err = errRequestCanceledConn}return nil, err}
}

image.png
因为连接的建议会消耗比较多的时间,带来较大的开下,所以Go语言使用了连接池对资源进行分配和复用,先调用 net/http.Transport.queueForIdleConn() 获取等待闲置的连接,如果没有获取到在调用net/http.Transport.queueForDial 在队列中等待建立新的连接,通过select监听连接是否建立完毕,超时未获取到连接会上剖错误,我们继续在queueForDial追踪TCP连接的建立:
image.png

启动一个goroutinetcp的建连,最终调用dialConn方法,在这个方法内做持久化连接,调用net库的dial方法进行TCP连接:
image.png
在连接建立后,代码中我们我们还看到分别启动了两个goroutine

  • readLoop用于从tcp连接中读取数据,
  • writeLoop用于从tcp连接中写入数据;

writeLoop方法监听writech通道,在循环中写入发送的数据。
image.png

net/http.Transport{}中提供了连接池配置参数,可以自定义

处理 HTTP 请求

net/http.persistConn.roundTrip() 处理HTTP请求
image.png

image.png
有两个通道:

  • pc.writech :其类型是chan writeRequest writeLoop协程会循环写入数据,net/http.Request.write会根据net/http.Request结构中的字段按照HTTP协议组成TCP数据段,TCP协议栈会负责将HTTP请求中的内容发送到目标服务器上;
  • pc.reqch:其类型是chan requestAndChanreadLoop协程会循环读取响应数据并且调用net/http.ReadResponse进行协议解析,其中包含状态码、协议版本、请求头等内容;

总结

  • net/http.Client是级别最高的抽象,其中transport用于开启HTTP事务,jar用于处理cookie
  • net/http.Transport中主要逻辑两部分:
    • 从连接池中获取持久化连接
    • 使用持久化连接处理HTTP请求

net/http库中默认有一个DefaultClient可以直接使用,DefaultClient有对应DefaultTransport,可以满足大多数场景。

  • 如果需要使用自己管理HTTP客户端的头域、重定向等策略,可以自定义Client
  • 如果需要管理代理、TLS配置、连接池、压缩等设置,可以自定义Transport

因为HTTP协议的版本是不断变化的,所以为了可扩展性,transport是一个接口类型,具体的是实现是Transporthttp2TransportfileTransport,这样实现扩展性变得很高。

HTTP在建立连接时会耗费大量的资源,需要开辟一个goroutine去创建TCP连接,连接建立后会在创建两个goroutine用于HTTP请求的写入和响应的解析,然后使用channel进行通信,所以要合理利用连接池,避免大量的TCP连接的建立可以优化性能;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_239701.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python——几个常用的数学函数

1. min()函数&#xff1a;取出给定参数的最小值 说明&#xff1a;获取指定数值或者指定序列中最小值。 print(min(1, 5)) print(min(1, 2, 3, 4, 5, 6)) print(min([2, 3, 4, 5])) 2.max()函数&#xff1a;取出给定参数的最大值 说明&#xff1a;获取指定数值或者指定序列中…

XDocReport使用入门

XDocReport 简介 XDocReport是GitHub上根据麻省理工学院许可证开源的Wrod导出框架。XDocReport可以根据ODT、Doc、Docx文档模板通过模板引擎语法&#xff08;Freemarker、Velocity&#xff09;转换为另外一种格式文档&#xff08;Doc、Docx、XHTML、PDF&#xff09;。 XDocR…

前端小知识:控制台打印(console)- 模拟Java日志打印、表格形式打印美化输出对象、代码运行时间统计

文章目录6. 控制台打印&#xff08;Console&#xff09;模拟Java日志打印格式美化对象打印&#xff08;表格形式打印输出&#xff09;日志等级输出&#xff08;让其在控制台显示时有颜色提示&#xff09;代码运行时间统计打印输出6. 控制台打印&#xff08;Console&#xff09;…

用树莓派4B安装gitlab,亲测可用~

最近成功在CentOS7上安装了gitlab&#xff0c;忽然想到是不是可以把吃灰的树莓派4B也装上gitlab&#xff0c;于是研究了一下&#xff0c;做个分享。 树莓派是4B 8G版本。本身装的是官方的64位系统。之前可能还装过一些乱七八糟的东西&#xff0c;这里就不提了。 上gitlab官网…

移动 IP(计算机网络-网络层)

目录 移动性对网络应用的影响 移动IP中数据报的转发过程 移动IP中数据报的转发过程 三角路由的低效性 解决三角路由的低效性 移动IP的标准 移动性对网络应用的影响 现在先考虑这样一种情况&#xff0c;一个用户拿着无线移动设备在一个Wi-Fi服务区内走动&#xff0c;并且边…

【python圣诞树的实现】

&#x1f935;‍♂️ 个人主页老虎也淘气 个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f44d;&#x1f3fb; 收藏…

http 库的服务端实现

前言 net/http 库的客户端实现(上) net/http 库的客户端实现(下) net/http 库的服务端实现 上两篇文章介绍了 http 客户端的实现&#xff0c;这篇文章看一下服务端的实现 服务端 使用 net/http 库可以快速搭建HTTP服务&#xff0c;HTTP服务端主要包含两部分&#xff1a; …

【圣诞特辑】码一个漂漂亮亮的圣诞树(Single Dog版)

目录 前言 一、C语言版圣诞树 1.代码实现 2.效果图 二、python版圣诞树 1.代码实现 2.效果图​ 三、html5版圣诞树 1.代码实现 2.效果图 总结 前言 圣诞节即将来临&#xff0c;圣诞树也是必不可少的装饰之一。圣诞树是一棵绿叶繁茂的树&#xff0c;上面挂满了彩色的灯…

Python pandas有好几百个库函数,你都用过吗(4)

上一篇链接&#xff1a; https://blog.csdn.net/boysoft2002/article/details/128428569 S~W&#xff1a; Function46~56 Types[Function][45:] [set_eng_float_format, show_versions, test, timedelta_range, to_datetime, to_numeric, to_pickle, to_timedelta, unique,…

VSCode 最全实用插件

一、必备插件 &#x1f33e;Chinese&#xff08;中文&#xff09; Settings Sync&#xff08;配置同步到云端&#xff09; 可以让我们的vscode配置同步到云端&#xff0c;当我们跟换电脑或者再次安装vscode的时候&#xff0c;只需要登录账号即可同步配置了 wakatime&#xf…

技术分享 Oracle下启用块跟踪

创建存放块跟踪文件目录 [oraclehost01 ~]$ cd /u01/app [oraclehost01 app]$ mkdir BCT 启用块跟踪 SQL> alter database enable block change tracking using file /u01/app/BCT/rman.bct; 检查块跟踪状态 SQL> col filename for a22 SQL> select filename, status,…

RabbitMQ——延迟队列

目录 一、延迟队列的应用场景 1. 场景&#xff1a;"订单下单成功后&#xff0c;15分钟未支付自动取消" ① 传统处理超时订单 ② RabbitMQ延时队列方案 二、延迟队列中的消息投递和消息消费 1.TTL 和 DLX ① TTL ② DLX和死信队列 ③ 延迟队列 ④ 开发步骤 …

get/post/put/delete请求头说明

目录 1.请求头说明 2.get 3.delete 4.post 5.put 6. 说明 7.Content-Type说明 1.请求头说明 前端发出的请求通过浏览器进行查看&#xff0c;可以发现分为四个部分。常规信息(General)&#xff0c;请求头信息(Request Headers)&#xff0c;响应头信息(Response Headers)…

ConvLSTM时空预测实战代码详解

写在前面 时空预测是很多领域都存在的问题&#xff0c;不同于时间序列&#xff0c;时空预测不仅需要探究时间的变化&#xff0c;也需要关注空间的变化。许多预测问题都只片面的关注时间问题&#xff0c;如预测某人未来3年患某种病的概率&#xff0c;食堂就餐人数等&#xff0c…

35. 池化层 / 汇聚层 代码实现

1. 池化层 在下面的代码中的pool2d函数&#xff0c;我们实现汇聚层的前向传播。 这类似于之前文章中的的corr2d函数。 然而&#xff0c;这里我们没有卷积核&#xff0c;输出为输入中每个区域的最大值或平均值。 from torch import nn from d2l import torch as d2l# X是输入&…

springcloud-gateway简介

目录 1. gateway简介 1.1 是什么 1.2 作用 1.3 主要特征 1.4 与zuul的主要区别 1.5 主要组件 1.6 架构图 2. 开发示例 2.1 创建一个gateway模块 2.2 与nacos结合使用 2.2.1 默认规则 2.2.2 通过配置文件配置路由 2.2.3 动态路由 1. gateway简介 1.1 是什么 SpringC…

VuePress初学之利用模板theme创建一个个人博客网站

目录前言官方文档创建项目创建目录安装VuePress初始化项目创建文档修改package.json运行项目修改README.md的编码显示官方默认主题创建.vuepress文件创建config.js修改README.md补充logo资源运行效果更多默认主题配置开源主题vuepress-theme-reco安装脚手架初始化项目安装npm运…

10.2、Django入门--前台管理

文章目录1、URLconf 路由管理展示首页2、视图函数处理业务逻辑展示书籍的详细页3、模板管理实现好看的HTML页面3.1 模板引擎配置3.2 模板语法&#xff1a;变量3.3 模板语法: 常用标签3.4 主页与详情页前端HTML设计常用的HTML编写基础标题标签列表标签图片标签链接标签表格标签表…

RabbitMQ 第一天 基础 6 SpringBoot 整合RabbitMQ

RabbitMQ 【黑马程序员RabbitMQ全套教程&#xff0c;rabbitmq消息中间件到实战】 文章目录RabbitMQ第一天 基础6 SpringBoot 整合RabbitMQ6.1 SpringBoot 整合 RabbitMQ【生产者】6.1.1 生产者6.2 SpringBoot 整合 RabbitMQ【消费者】6.2.1 消费者6.3 小结第一天 基础 6 Spri…

day3-javascript

HTML的注释 CSS的注释 Javascript的注释是不一样的 JQuery JQuery是一个JavaScript的第三方模块 基于JQuery&#xff0c;自己开发一个功能。 现成的工具 依赖jQuery&#xff0c;例如BootStrap动态效果