netx

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Nov 20, 2025 License: MIT Imports: 4 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 and net.Conn. 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. Zero Intrusion: All components return a standard net.Listener, making them directly usable with http.Server, grpc.Server, or any framework that accepts a standard Listener.

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 basic Listener
    ln, _ := net.Listen("tcp", ":8080")

    // 2. Wrap it like an onion
    ln = netx.Chain(ln,
        // [Performance] Enable TCP KeepAlive (Default: 3 minutes)
        netx.WithKeepAlive(0),
        
        // [Protection] Limit max concurrent connections to 10,000 to prevent OOM
        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
    connContext := netx.GetContext(r.Context().Value(http.LocalAddrContextKey).(net.Conn))
    
    select {
    case <-connContext.Done():
        println("TCP connection closed, stop processing")
    }
}
2. Traffic Shaping

Implement complex rate-limiting logic (e.g., Global limits, Single IP limits, VIP bypass) through policy injection.

  • Mechanism: Intercepts Read/Write.
  • Policy: User injected via ShaperFactory.
// Define your rate limiting policy
factory := func(c net.Conn) (read, write netx.Bucket) {
    ip := getIP(c.RemoteAddr())
    if isVIP(ip) {
        return nil, nil // No limit for VIPs
    }
    // Normal users use token bucket (requires implementing netx.Bucket interface)
    return globalRateLimiter, globalRateLimiter 
}

ln = netx.WithShaper(factory)
3. Overload Protection
  • WithLimit(n): Uses a semaphore mechanism to limit the maximum number of concurrent connections. When the limit is reached, Accept for new connections will block (handled by the kernel backlog), protecting the Server from being overwhelmed by traffic spikes.
4. Observability

netx does not bind to any specific metrics library (like Prometheus). Instead, it provides pure callback hooks.

ln = netx.WithObserve(func(c net.Conn, state netx.ConnState) {
    if state == netx.StateOpen {
        metrics.ActiveConns.Inc()
    } else {
        metrics.ActiveConns.Dec()
    }
})

Best Practices

It is recommended to encapsulate default combination logic within your server package, following the "Default to Secure & Observable" principle:

func Listen(addr string) (net.Listener, error) {
    l, err := net.Listen("tcp", addr)
    if err != nil { return nil, err }
    
    return netx.Chain(l,
        netx.WithKeepAlive(0),      // Always enable
        netx.WithContext(nil),      // Always bind lifecycle
        netx.WithLimit(50000),      // Always set safety limit
        netx.WithObserve(myMetrics),// Always enable monitoring
    ), nil
}

Contribution

Issues and PRs are welcome to enrich netx capabilities (e.g., WithTLS, WithProxyProtocol, etc.). Please maintain the Zero Dependency principle.

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 GetContext

func GetContext(c net.Conn) context.Context

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

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 Middleware

type Middleware func(net.Listener) net.Listener

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

func WithContext

func WithContext(factory ContextFactory) Middleware

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

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 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 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