golang的http client源码简析

yuanyangen · · 9345 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

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中




有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:yuanyangen

查看原文:golang的http client源码简析

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

9345 次点击  
加入收藏 微博
2 回复  |  直到 2020-06-22 16:19:51
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传