单端口映射多进程负载服务器

2022-05-16  本文已影响0人  追风骚年

一般来说一个端口只能绑定一个进程,然而在 Linux 中其实有一个参数选项 SO_REUSEPORT ,可以让一个端口被多个进程监听,本意是解决 Tcp 的 TIME_WAIT 问题,但是于我看来其实可以做多进程负载到一个端口上。

golang 中可以通过如下实现:

package main

import (
    "context"
    "fmt"
    "golang.org/x/sys/unix"
    "net"
    "net/http"
    "os"
    "syscall"
)

func main() {
    http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
        writer.Write([]byte(fmt.Sprintf("from pid: %d", os.Getpid())))
    })

    server := &http.Server{Addr: "127.0.0.1:8080", Handler: http.DefaultServeMux}

    lc := net.ListenConfig{
        Control: func(network, address string, c syscall.RawConn) error {
            return c.Control(func(fd uintptr) {
                fmt.Println("Control SO_REUSEADDR :", syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1))
                fmt.Println("Control SO_REUSEPORT :", syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1))
            })
        },
    }

    lis, err := lc.Listen(context.Background(), "tcp", server.Addr)
    if err != nil {
        panic(err)
    }

    panic(server.Serve(lis))
}

目前服务可以运行很多次,每次都运行在一个进程上,但是这些进程都绑定到同一个端口上,确实很神奇,在我测试下来,Linux 上确实是可以做到随机负载,Mac 是不支持随机负载的,只会连接到最后一个启动的进程。

上一篇下一篇

猜你喜欢

热点阅读