Skip to content

feat(evpp): implement LB_IpHash load balance strategy - #879

Merged
ithewei merged 1 commit into
masterfrom
feat-lb-iphash
Sep 15, 2026
Merged

ithewei merged 1 commit into
masterfrom
feat-lb-iphash

Conversation

@ithewei

@ithewei ithewei commented Sep 15, 2026

Copy link
Copy Markdown
Owner

What

Implements the LB_IpHash load balance strategy, which was already declared in load_balance_e (event/hloop.h) but left as // Not Implemented in EventLoopThreadPool::nextLoop().

With LB_IpHash, all connections from the same client IP are consistently dispatched to the same worker loop.

Changes

  • base/hsocket.{h,c}: add sockaddr_ip_hash() (C layer, so C users can also use it). FNV-1a over the IP bytes only — port excluded — so the same client IP maps to a stable value. IPv4 hashes 4 bytes, IPv6 hashes 16 bytes.
  • evpp/EventLoopThreadPool.h: nextLoop() gains an optional uint32_t hash = 0 arg (backward compatible). LB_IpHash selects idx = hash % numLoops; the previously empty else now falls back to RoundRobin instead of always returning loop 0.
  • evpp/TcpServer.h: onAccept() computes the peer IP hash via hio_peeraddr() when the strategy is LB_IpHash.
  • docs/cn/TcpServer.md: document the available load balance options.

Drive-by bug fixes in base/hsocket.c

Two pre-existing bugs spotted while working in this file:

  • sockaddr_compare: the IPv6 branch compared only 4 bytes (sizeof(struct in_addr)) instead of the full 16-byte in6_addr, so IPv6 addresses differing beyond the first 4 bytes were incorrectly treated as equal.
  • ResolveAddr: the IPv6-literal branch was missing a return 0;, causing a redundant (potentially blocking) getaddrinfo() call that then overwrote the already-parsed literal result.

Notes

  • LB_UrlHash is still unimplemented: at accept time there is no application-layer data, so the URL is unavailable. It belongs to the HTTP layer, not TcpServer. The else fallback keeps behavior safe (RoundRobin) if it is ever selected.

Testing

  • make libhv
  • make evpp ✅ (all C++ test binaries link)
  • IpHash dispatch behavior (multiple workers + multiple client IPs mapping to a stable loop) is intended for manual verification.

Wire up the LB_IpHash strategy that was declared in load_balance_e but
left unimplemented in EventLoopThreadPool::nextLoop().

- add sockaddr_ip_hash() in base (C layer), FNV-1a over the ip bytes only
  (port excluded) so the same client ip maps to the same worker loop
- nextLoop() gains an optional hash arg; LB_IpHash selects idx = hash % n,
  and the previously empty else branch now falls back to RoundRobin
- TcpServer::onAccept computes the peer ip hash when LB_IpHash is set
- docs/cn/TcpServer.md: document the load balance options

Also fix two pre-existing bugs in base/hsocket.c spotted along the way:
- sockaddr_compare: IPv6 branch compared only 4 bytes (sizeof in_addr)
  instead of the full 16-byte in6_addr, so IPv6 addrs differing beyond
  the first 4 bytes were treated as equal
- ResolveAddr: IPv6 literal branch was missing a return, causing a
  redundant getaddrinfo() call that could overwrite the parsed result

Co-authored-by: TRAE CLI <traecli@bytedance.com>
Copilot AI lite review requested due to automatic review settings September 15, 2026 03:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

An automated behavioral test for LB_IpHash is still needed.

Pull request overview

Implements client-IP-based load balancing for TcpServer, with socket hashing, IPv6 fixes, and documentation updates.

Changes:

  • Adds FNV-1a hashing for IPv4 and IPv6 addresses.
  • Implements LB_IpHash routing with RoundRobin fallback.
  • Fixes IPv6 comparison and literal address resolution.
  • Documents load-balance strategies.
File summaries
File Summary
evpp/TcpServer.h Computes peer-IP hashes during accept.
evpp/EventLoopThreadPool.h Adds hash-based dispatch and fallback behavior.
docs/cn/TcpServer.md Documents load-balance strategies.
base/hsocket.h Declares the IP hash helper.
base/hsocket.c Implements hashing and socket-address fixes.
Review details

Suppressed comments (2)

evpp/EventLoopThreadPool.h:32

  • The public API reference in docs/cn/EventLoop.md:92 still declares nextLoop(load_balance_e lb = LB_RoundRobin) and omits both the new hash parameter and LB_IpHash. A caller following that documentation cannot provide the key and will silently use the default hash 0, routing every LB_IpHash call to worker 0; update that reference and its strategy list with this API change.
    EventLoopPtr nextLoop(load_balance_e lb = LB_RoundRobin, uint32_t hash = 0) {

evpp/EventLoopThreadPool.h:48

  • The new LB_IpHash branch has no automated behavioral test: EventLoopThreadPool_test.cpp only prints selected loop IDs, and CI does not execute that binary. Add a deterministic test covering equal IP hashes (including different ports) and hashes that map to different workers before relying on manual verification.
            idx = hash % numLoops;
  • Files reviewed: 5/5 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@ithewei
ithewei merged commit 35d42f3 into master Sep 15, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants