netx

package module
v1.4.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 14, 2026 License: MIT Imports: 10 Imported by: 1

README

netx: Network Extensions for Go

Go Report Card

中文 | English

netx is a zero-dependency, high-performance network layer extension library for Go.

Designed based on the Decorator Pattern, it aims to enhance the standard net.Listener, net.Conn, and net.PacketConn. It provides Lifecycle Management, Overload Protection, Traffic Shaping, and Observability for the underlying network layer while maintaining perfect compatibility with the standard library.

Core Philosophies

  1. Mechanism over Policy: netx only provides the underlying mechanisms for "how to limit rates" or "how to collect stats." Decisions on "what the rate limit is" or "where to send stats" are entirely controlled by the user via callbacks or factory injection.
  2. Onion Model & Context Penetration: Through a unified Wrapper interface, it supports Context penetration from the outermost layer to the innermost layer, bridging the lifecycle between L4 (TCP) and L7 (Application).
  3. Universal Compatibility: All components return standard net.Listener or net.PacketConn, making them directly usable with http.Server, grpc.Server, quic-go, or any framework.

Installation

go get github.com/oy3o/netx

Quick Start

Use Chain to combine multiple features like building blocks:

package main

import (
    "net"
    "net/http"
    "time"
    
    "github.com/oy3o/netx"
)

func main() {
    // 1. Create a Listener with SO_REUSEPORT enabled (High Performance)
    ln, _ := netx.ListenTCP("tcp", ":8080", netx.ListenConfig{
        EnableReusePort: true, 
    })

    // 2. Wrap it like an onion
    ln = netx.Chain(ln,
        // [Performance] Enable TCP KeepAlive (Default: 3 minutes)
        netx.WithKeepAlive(0),
        
        // [Safety] Set Initial I/O Deadlines (Prevent Slowloris attacks)
        netx.WithIOTimeout(5*time.Second, 5*time.Second),
        
        // [Protection] Limit max concurrent connections to 10,000
        netx.WithLimit(10000),
        
        // [Lifecycle] Bind Context; auto-cancel Context when connection closes
        netx.WithContext(nil),
    )

    // 3. Start standard HTTP Server
    http.Serve(ln, nil)
}

Core Components

1. Lifecycle (Context & Lifecycle)

Introducing context.Context at the TCP layer is one of the most powerful features of netx.

  • Function: Binds a Context to every connection. When the physical connection is closed (Close), the Context is automatically cancelled (Done).
  • Usage: Business logic can listen to the Context to implement graceful exits or resource cleanup.
ln = netx.WithContext(func(c net.Conn) context.Context {
    // Optional: Inject TraceID or Logger here
    return context.WithValue(context.Background(), "trace_id", uuid.NewString())
})

// Access in business code:
func HandleRequest(w http.ResponseWriter, r *http.Request) {
    // GetContext can recursively find the deepest Context even through layers of wrappers
    // It even works through TLS connections!
    connContext := netx.GetContext(r.Context().Value(http.LocalAddrContextKey).(net.Conn))
    
    select {
    case <-connContext.Done():
        println("TCP connection closed, stop processing")
    }
}
2. Traffic Shaping (TCP & UDP)

Implement complex rate-limiting logic through policy injection.

  • TCP (WithShaper): Intercepts Read/Write with Token Bucket algorithm.
  • UDP (WithPPSLimit): Limits Packets Per Second for Read/Write.
// TCP Traffic Shaping
factory := func(c net.Conn) (read, write netx.Bucket) {
    ip := getIP(c.RemoteAddr())
    if isVIP(ip) {
        return nil, nil // No limit for VIPs
    }
    return globalRateLimiter, globalRateLimiter 
}
ln = netx.WithShaper(factory)

// UDP PPS Limiting (e.g. for QUIC)
pc = netx.WithPPSLimit(netx.LimitConfig{
    Read:  rate.NewLimiter(rate.Limit(1000), 100), // Max 1000 pps Rx
    Write: rate.NewLimiter(rate.Limit(1000), 100), // Max 1000 pps Tx
})(pc)
3. Security & Protection
  • WithLimit(n): Uses a semaphore to limit max concurrent connections. Blocks Accept when full.
  • WithIOTimeout(read, write): Sets a deadline on Accept. Essential for defending against Slowloris attacks where clients hold connections open without sending data.
4. Infrastructure & Proxy
  • WithProxyProtocol: Adds support for HAProxy PROXY protocol. Essential when your service is deployed behind an L4 Load Balancer (AWS ELB, Nginx Stream) and you need the real client IP.
5. QUIC / HTTP3 Optimization

netx provides specific optimizations for UDP protocols like QUIC:

  • WithUDPBuffer(rx, tx): Adjusts kernel socket buffer sizes (SO_RCVBUF/SO_SNDBUF). High-speed QUIC transfers require larger buffers (e.g., 2MB-4MB) to prevent packet loss.
  • EnableReusePort: Allows multiple processes to bind to the same port, enabling kernel-level load balancing.
pc, _ := netx.ListenUDP("udp", ":443", netx.ListenConfig{EnableReusePort: true})

pc = netx.ChainUDP(pc,
    netx.WithUDPBuffer(4*1024*1024, 4*1024*1024), // 4MB Buffer
    netx.WithPPSLimit(limitCfg),
)
Context Penetration & AsTCPConn

netx wrappers allow you to reach deep into the connection stack.

  • GetContext(conn): Retrieves the lifecycle context bound to the connection, even through TLS layers.
  • AsTCPConn(conn): Recursively unwraps layers (Metrics -> Limiter -> TLS) to return the underlying *net.TCPConn.
// Example: Setting TCP NoDelay on a wrapped TLS connection
if tc := netx.AsTCPConn(req.Context().Value(http.LocalAddrContextKey).(net.Conn)); tc != nil {
    tc.SetNoDelay(true)
}

Best Practices

Encapsulate default logic within your server package, following the "Default to Secure & Observable" principle:

func Listen(addr string) (net.Listener, error) {
    // 1. Use ReusePort for performance
    l, err := netx.ListenTCP("tcp", addr, netx.ListenConfig{EnableReusePort: true})
    if err != nil { return nil, err }
    
    return netx.Chain(l,
        netx.WithKeepAlive(0),                            // KeepAlive
        netx.WithIOTimeout(5*time.Second, 5*time.Second), // Safety
        netx.WithContext(nil),                            // Lifecycle
        netx.WithLimit(50000),                            // Max Conns
        netx.WithObserve(myMetrics),                      // Metrics
    ), nil
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AsTCPConn added in v1.0.0

func AsTCPConn(c net.Conn) *net.TCPConn

AsTCPConn 尝试将 net.Conn 还原为 *net.TCPConn 即使被多层 Wrapper 包裹也能找到。

func Chain

func Chain(l net.Listener, mws ...Middleware) net.Listener

Chain 是一个辅助函数,用于将多个中间件应用到一个 Listener 上。 顺序:Chain(l, A, B, C) -> C(B(A(l))) 越靠后的中间件越外层(越先处理 Accept)。

func ChainUDP added in v1.4.0

func ChainUDP(c net.PacketConn, mws ...UDPMiddleware) net.PacketConn

ChainUDP 串联 UDP 中间件

func GetContext

func GetContext(c any) context.Context

GetContext 递归地尝试从连接中获取上下文。 如果连接没有绑定 Context,返回 context.Background()。

func ListenTCP added in v1.4.0

func ListenTCP(network, address string, cfg ListenConfig) (net.Listener, error)

ListenTCP 创建一个 TCP 监听器

func ListenUDP added in v1.4.0

func ListenUDP(network, address string, cfg ListenConfig) (net.PacketConn, error)

ListenUDP 创建一个 UDP 连接(用于 QUIC/HTTP3)

Types

type Bucket

type Bucket interface {
	// Take 阻塞等待,直到获取到 tokens 个令牌。
	// ctx 可用于取消等待。
	Take(ctx context.Context, tokens int64) error
}

Bucket 是一个抽象的令牌桶接口。 外部可以使用 time/rate 或 juju/ratelimit 实现此接口。

type ConnState

type ConnState int
const (
	StateOpen  ConnState = iota // 连接建立
	StateClose                  // 连接关闭
)

type ContextFactory

type ContextFactory func(net.Conn) context.Context

ContextFactory 允许用户自定义 Context 的初始化逻辑(例如注入 TraceID, Logger)。

type ContextGetter

type ContextGetter interface {
	Context() context.Context
}

ContextGetter 接口用于直接获取连接绑定的上下文。

type LimitConfig added in v1.4.0

type LimitConfig struct {
	Read  *rate.Limiter // 入站限流 (nil 表示不限制)
	Write *rate.Limiter // 出站限流 (nil 表示不限制)
}

LimitConfig 定义限流配置

type ListenConfig added in v1.4.0

type ListenConfig struct {
	// EnableReusePort 开启 SO_REUSEPORT 特性
	// 允许在多核机器上启动多个进程/线程监听同一端口,由内核进行负载均衡
	EnableReusePort bool
}

ListenConfig 封装监听配置

type Middleware

type Middleware func(net.Listener) net.Listener

Middleware 定义了 Listener 的装饰器函数签名。

func WithContext

func WithContext(factory ContextFactory) Middleware

WithContext 返回一个中间件,用于为每个连接绑定生命周期上下文。 当连接 Close 时,Context 会自动 Cancel。

func WithIOTimeout added in v1.4.0

func WithIOTimeout(read, write time.Duration) Middleware

WithIOTimeout 设置读写超时。 这是一个非常重要的安全配置,防止客户端建立连接后不发送数据(Slowloris 攻击)。

func WithKeepAlive

func WithKeepAlive(period time.Duration) Middleware

WithKeepAlive 返回一个中间件,自动开启 TCP KeepAlive。 period: 探测间隔。如果为 0,默认使用 3 分钟。

func WithLimit

func WithLimit(n int) Middleware

WithLimit 返回一个中间件,限制最大并发连接数。

func WithObserve

func WithObserve(observer Observer) Middleware

WithObserve 返回一个中间件,用于监控连接的开启和关闭。

func WithProxyProtocol added in v1.4.0

func WithProxyProtocol(trustedCIDRs []string) Middleware

WithProxyProtocol 启用 HAProxy PROXY 协议解析。 trustedCIDRs: 允许发送 PROXY 头的来源 IP 网段 (如 "10.0.0.0/8", "127.0.0.1/32")。 如果连接来自非信任 IP,将跳过 PROXY 解析(视为普通 TCP 连接),防止 IP 伪造。

func WithShaper

func WithShaper(factory ShaperFactory) Middleware

WithShaper 返回一个中间件,用于对连接进行流量整形(限速)。

type Observer

type Observer func(net.Conn, ConnState)

Observer 定义了观测回调函数签名

type ShaperFactory

type ShaperFactory func(net.Conn) (readBucket, writeBucket Bucket)

ShaperFactory 根据连接信息返回读写限速器。 如果返回 nil,表示不限制。

type UDPMiddleware added in v1.4.0

type UDPMiddleware func(net.PacketConn) net.PacketConn

UDPMiddleware 定义 UDP 连接装饰器

func WithPPSLimit added in v1.4.0

func WithPPSLimit(cfg LimitConfig) UDPMiddleware

WithPPSLimit 限制 UDP 的每秒包数。

func WithUDPBuffer added in v1.4.0

func WithUDPBuffer(readBuf, writeBuf int) UDPMiddleware

WithUDPBuffer 设置内核缓冲区大小 QUIC 协议强烈建议增大 UDP 缓冲区以提升吞吐量并减少丢包

type Wrapper

type Wrapper interface {
	Unwrap() net.Conn
}

Wrapper 接口允许解包底层的连接。 所有 netx 的装饰器连接都必须实现此接口,以支持上下文穿透。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL