Posts

Showing posts from June, 2022

Golang 中的TCP_NODELAY控制数据包及流量

编写 Web 服务需要大量的努力和思考,才能使它们变得健壮和高性能。为了提高我们服务的性能,有广泛的领域需要研究。我们可以从改进代码本身开始,如果我们进入优化的兔子洞,我们也可能开始研究垃圾回收器,操作系统,网络级别以及托管我们服务的硬件。 这篇博客文章将触及一些网络算法的表面,当我们试图提高Web服务的性能时,这些算法可能会派上用场。我们将介绍套接字选项,看看如何在没有任何外部软件包的情况下在Go中控制它。 TCP_NODELAY 一些理论 大多数平台上的TCP实现 都提供 算法和套接字选项来决定数据包流,连接寿命等等。影响网络性能并在Linux,macOS和Windows上默认启用 的算法是Nagle的算法 。Nagle的算法合并小数据包并延迟其传递,直到从先前发送的数据包返回ACK或在一定时间后累积足够数量的小数据包。此过程通常需要毫秒,但是,对于延迟敏感型服务或严格的延迟 服务级别目标 (SLO), 减少几毫秒可能是值得的。 此处非常有用的跨平台 TCP 套接字选项是 。启用后,它实际上会禁用Nagle的算法。它不是合并小包,而是尽快将它们发送到管道。一般来说,Nagle算法的目标是减少发送的数据包数量,以节省带宽和增加吞吐量,有时还需要权衡增加服务延迟。另一方面,可能会降低小型写入的吞吐量,但有一些方法可以通过在应用程序端使用缓冲区来 缓解 这种情况。 TCP_NODELAY TCP_NODELAY 在 Go 中,默认情况下处于启用状态,但标准库提供了通过网络禁用行为 的功能。SetNoDelay  方法。 TCP_NODELAY 一个小实验 为了观察数据包级别发生的情况,并查看数据包到达的差异,我们将使用一个用Go编写的小型TCP客户端/服务器。通常,我们在不同地区都有相互连接的服务,但为了实验,我们将在本地机器上进行实验。完整的源代码也可以在 Github 上找到。 服务器代码 (server.go): 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 package main

实战:150行Go实现高性能socks5代理

Image
光说不练假把式,不如上手试试,这篇来写个有点卵用的东西。 TCP Server 用 Go 实现一个 TCP Server 实在是太简单了,什么 c10k problem、select、poll、epoll、kqueue、iocp、libevent,通通不需要( 但为了通过面试你还是得去看呀 ),只需要这样两步: 监听端口 1080(socks5的默认端口) 每收到一个请求,启动一个 goroutine 来处理它 搭起这样一个架子,实现一个 Hello world,大约需要 30 行代码: func main () { server, err := net .Listen ( "tcp" , ":1080" ) if err != nil { fmt .Printf ( "Listen failed: %v\n" , err) return } for { client, err := server .Accept () if err != nil { fmt .Printf ( "Accept failed: %v" , err) continue } go process (client) } } func process (client net.Conn) { remoteAddr := client .RemoteAddr () .String () fmt .Printf ( "Connection from %s\n" , remoteAddr) client .Write ( [] byte ( "Hello world!\n" )) client .Close () } SOCKS5 socks5 是 SOCKS Protocol Version 5 的缩写,其规范定义于  RFC 1928 [1],感兴趣的同学可以自己去翻一翻。 它是个二进制协议,不那么直观,不过实际上非常简单,主要分成三个步骤: 认证 建立连接 转发数据 我们只需 16 行就能把 socks5 的架子搭起来: func process(client