replace (

golang.org/x/crypto => github.com/golang/crypto v0.0.0-20190313024323-a1f597ede03a

golang.org/x/sys => github.com/golang/sys v0.0.0-20190318195719-6c81ef8f67ca

golang.org/x/text => github.com/golang/text v0.3.0

golang.org/x/lint => github.com/golang/lint v0.0.0-20190409202823-959b441ac422

golang.org/x/time => github.com/golang/time v0.0.0-20190308202827-9d24e82272b4

golang.org/x/tools => github.com/golang/tools v0.0.0-20190529010454-aa71c3f32488

golang.org/x/oauth2 => github.com/golang/oauth2 v0.0.0-20190523182746-aaccbc9213b0

golang.org/x/net => github.com/golang/net v0.0.0-20190318221613-d196dffd7c2b

golang.org/x/exp => github.com/golang/exp master

cloud.google.com/go => github.com/googleapis/google-cloud-go master

google.golang.org/genproto => github.com/google/go-genproto v0.0.0-20190522204451-c2c4e71fbf69

google.golang.org/grpc => github.com/grpc/grpc-go v1.21.0

google.golang.org/appengine => github.com/golang/appengine v1.6.1-0.20190515044707-311d3c5cf937

golang.org/x/sync => github.com/golang/sync v0.0.0-20190227155943-e225da77a7e6

)

DPDK(Data Plane Development Kit),是一组快速处理数据包的开发平台及接口。运行于Intel X86与arm平台上(最新版本也开始支持PowerPC)。

概述

在X86结构中,处理数据包的传统方式是CPU中断方式,即网卡驱动接收到数据包后通过中断通知CPU处理,然后由CPU拷贝数据并交给协议栈。在数据量大时,这种方式会产生大量CPU中断,导致CPU无法运行其他程序。

而DPDK则采用轮询方式实现数据包处理过程:DPDK重载了网卡驱动,该驱动在收到数据包后不中断通知CPU,而是将数据包通过零拷贝技术存入内存,这时应用层程序就可以通过DPDK提供的接口,直接从内存读取数据包。

这种处理方式节省了CPU中断时间、内存拷贝时间,并向应用层提供了简单易行且高效的数据包处理方式,使得网络应用的开发更加方便。但同时,由于需要重载网卡驱动,因此该开发包目前只能用在部分采用Intel网络处理芯片的网卡中。

x86网络io瓶颈

  • 传统的收发报文方式都必须采用硬中断来做通讯,每次硬中断大约消耗100微秒,这还不算因为终止上下文所带来的Cache Miss。
  • 数据必须从内核态用户态之间切换拷贝带来大量CPU消耗,全局锁竞争。
  • 收发包都有系统调用的开销。
  • 内核工作在多核上,为可全局一致,即使采用Lock Free,也避免不了锁总线、内存屏障带来的性能损耗。
  • 从网卡到业务进程,经过的路径太长,有些其实未必要的,例如netfilter框架,这些都带来一定的消耗,而且容易Cache Miss。

DPDK生态

腾讯云开源的F-Stack

Seastar也很强大和灵活,内核态和DPDK都随意切换,也有自己的传输协议Seastar Native TCP/IP Stack支持,但是目前还未看到有大型项目在使用Seastar,可能需要填的坑比较多。

http2 over tls1.2 tls1.3 quic RTT对比

methodHTTP/2 OVER TLS1.2首次连接HTTP/2 OVER TLS1.2连接恢复HTTP/2 OVER TLS1.3首次连接HTTP/2 OVER TLS1.3连接恢复HTTP/2 OVER QUIC首次连接HTTP/2 OVER QUIC连接恢复
DNS解析1RTT0RTT1RTT0RTT1RTT0RTT
TCP握手1.5RTT1.5RTT1.5RTT1.5RTT--
TLS握手2RTT1RTT1RTT0RTT--
QUIC握手----1RTT0RTT
HTTP Request1RTT1RTT1RTT1RTT1RTT1RTT
总计5.5RTT3.5RTT4.5RTT2.5RTT3RTT1RTT

TLS 1.0 RFC https://www.ietf.org/rfc/rfc2246.txt

TLS 1.1 RFC https://www.ietf.org/rfc/rfc4346.txt

TLS 1.2 RFC https://www.ietf.org/rfc/rfc5246.txt

TLS 1.3 RFC https://www.ietf.org/rfc/rfc8446.txt


      Client                                               Server

      ClientHello                  -------->
                                                      ServerHello
                                                     Certificate*
                                               ServerKeyExchange*
                                              CertificateRequest*
                                   <--------      ServerHelloDone
      Certificate*
      ClientKeyExchange
      CertificateVerify*
      [ChangeCipherSpec]
      Finished                     -------->
                                               [ChangeCipherSpec]
                                   <--------             Finished
      Application Data             <------->     Application Data

TLS 1.2 完整握手过程( 来自 RFC 5246 )

       Client                                           Server

Key  ^ ClientHello
Exch | + key_share*
     | + signature_algorithms*
     | + psk_key_exchange_modes*
     v + pre_shared_key*       -------->
                                                  ServerHello  ^ Key
                                                 + key_share*  | Exch
                                            + pre_shared_key*  v
                                        {EncryptedExtensions}  ^  Server
                                        {CertificateRequest*}  v  Params
                                               {Certificate*}  ^
                                         {CertificateVerify*}  | Auth
                                                   {Finished}  v
                               <--------  [Application Data*]
     ^ {Certificate*}
Auth | {CertificateVerify*}
     v {Finished}              -------->
       [Application Data]      <------->  [Application Data]

TLS 1.3 完整握手过程( 来自 RFC 8446 )

  • +表示该报文中值得注意的extension
  • *表示该内容也可能不被发送
  • {} 表示该内容使用handshake_key加密
  • [] 表示该内容使用application_key加密

在完全握手情况下,TLS 1.3需要1-RTT建立连接。与TLS1.2有两点不同:握手过程中移除了ServerKeyExchange和ClientKeyExchange, DH (Diffie-Hellman) 参数通过 key_share 传输。

如果切片的容量小于1024个元素,那么扩容的时候slice的cap就翻番,乘以2;一旦元素个数超过1024个元素,增长因子就变成1.25,即每次增加原来容量的四分之一。
如果扩容之后,还没有触及原数组的容量,那么,切片中的指针指向的位置,就还是原数组,如果扩容之后,超过了原数组的容量,那么,Go就会开辟一块新的内存,把原来的值拷贝过来,这种情况丝毫不会影响到原数组。