golang的http client源码简析

本文简要分析了Go语言1.5.2版本中http客户端的源码,涉及HTTP响应gzip解码过程、代码逻辑结构以及连接池管理。在gzip解码问题中,解释了如何通过接口实现解压;代码逻辑主要集中在网络相关操作,虽然命名可能引起误解,但层次清晰;连接池管理使用协程和通道实现,保证了连接的复用和高效管理。
摘要由CSDN通过智能技术生成

RT: 有注释信息的代码在:https://github.com/yuanyangen/go_learning/tree/master/src/learning

上述代码是从golang1.5.2中得到的http部分源代码

在分析该源码过程中, 得到的简易流程图是:


在上述的流程中:不同颜色的方框表示不同的协程, 上图并没有完全将所有的细节 都展示出来,只是一个最基本的功能的描述, 而方框中的文字表示该处理的代码在哪个包下面的具体函数。


对于具体的详细处理流程, 请查看源代码。

在代码中出现的部分问题

1: 如果http响应t经过了gzip编码, 那么是什么时候进行解码的?

在代码位置: https://github.com/yuanyangen/go_learning/blob/master/src/learning/transport.go#L956, 

如果在

resp.Body = &gzipReader{body: resp.Body}

代码之前使用

msg,_:= ioutil.ReadAll(resp.Body)

fmt.Println将body中的信息打印出来, 那么得到的饿信息就是经过gzip编码的,

在956行之后将代码打印出来, 得到的信息就是gzip解码之后的, 这个是为什么?

答案在于接口,这个就是golang的接口的一种用法:

在这个代码中, 传入ioutil.ReadAll方法的参数需要时实现了readcloser 接口的一个指针,就是说任何对象或者指针,只要其实现了read方法和close方法, 就能够传入到这个函数中, 最初在调用956行之前, ioutil.readAll方法最终会调用byte.readFrom方法, 代码如下:

https://github.com/golang/go/blob/master/src%2Fbytes%2Fbuffer.go#L176

注意在176hang中的read方法, 这个就是问题的关键,如果传入的参数是gzipreader的方法, 则最终会调用gzipReaderd的read方法。而在这个方法中, 定义了对gzip的解压, 而这就是在代码注释中的“lanzily call的意思”。


2:整个代码的逻辑是否略显混乱?整个代码的层级结构是怎样的?

这个代码实际上都是http包,无论是roundtrip, 还是transport, 都是网络相关的东西, 并不是tcp/ip的传输层,只是他在代码实现的过程中取了这个名字, 让我有点误解。

3:http连接池的管理方式

长链接一般是在应用层中进行处理的,首先说长连接就是充分利用了tcp的连接特性,在一次建立了一次tcp的连接后, 并没有立马将连接断开, 而是将这个保留起来作为下一个请求使用, 这个涉及到哪些方面“

1: 谁能复用连接? 只有访问特定IP的特定端口(这里一般指定了协议),那么下一次的访问就能否复用上一次建立, 同时还没有断开的连接

2:连接池是什么? 就是对1里面提到的连接的管理的数据, 可以可以是各种数据结构, 在golang的http client中, 是通过协程和chan实现的, 实现的方式如图:


图如下:


在这个连接池管理的模型中, 所有的连接信息都保存在idleConn与idleConnCh之中, 其中这两个都是关联数组, 而其中的key都是连接的信息, 所以对于每个同样的连接需求而言,不同的协程之间就通过存在于idleConnch中的channel进行通信, 而已经建立的连接就放在idleConn中



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值