zoukankan      html  css  js  c++  java
  • tcp并发服务器(c20w)

    ** 原创文章,请勿转载 **

    并发服务器是一个老生常谈的话题,今天这里也写一个。

    1. 目标

        同时在线连接20万(c20w)。  

        开发语言:重要的事情说三遍,GOLANG, GOLANG, GOLANG!

        那为什么是20W,不是30W或其它? 这个数字随意。   :)


    2. 环境

        虚拟机(xenserver),    虚出6台机器(OS: CentOS 6.6 64bit) :
           . 一台服务器8核CPU,2G内存
           . 五台客户端2核CPU,2G内存
          

    3.  改centos几个参数, 6台机器一样:
      
    # ulimit -a   

          看 open files
          改成300000(大于20W就行) :
       #  ulimit -n 300000

       改端口范围
      
    # echo 1025 65000 > /proc/sys/net/ipv4/ip_local_port_range

    4. golang代码

        服务端: server.go

    package main
    
    import (
        "log"
        "net"
        "sync"
        "time"
    )
    
    func main() {
        tcpAddr, err := net.ResolveTCPAddr("tcp", ":5000")
    
        if err != nil {
            log.Fatalln("net.ResolveTCPAddr fail", err)
        }
    
        listener, err := net.ListenTCP("tcp4", tcpAddr)
        if err != nil {
            log.Println("server failed to start...")
            return
        }
    
        defer listener.Close()
        go print()
        log.Println("begin listening, addr : ", tcpAddr)
    
        for {
            conn, err := listener.Accept()
            if err != nil {
                log.Println("socket accept failed. reason: ", err)
                continue
            }
    
            go handleConnection(conn)
        }
    
    }
    
    func print() {
        ticker := time.NewTicker(5 * time.Second)
    
        for {
            <-ticker.C
            log.Println(len(clients.Map))
        }
    }
    
    var num = 0
    var num2 = 0
    var clients = Clients{Map: make(map[string]int, 0)}
    
    type Clients struct {
        sync.RWMutex
        Map map[string]int
    }
    
    func (c *Clients) Add(ip string) {
        c.Lock()
        c.Map[ip] = 1
        c.Unlock()
    }
    
    func (c *Clients) Del(ip string) {
        c.Lock()
        delete(c.Map, ip)
        c.Unlock()
    }
    func handleConnection(conn net.Conn) {
        ip := conn.RemoteAddr().String()
        clients.Add(ip)
    
        buf := make([]byte, 64)
        for {
            _, err := conn.Read(buf)
            //log.Println("n=", n)
            if err != nil {
                //log.Println(err)
                conn.Close()
                clients.Del(ip)
            }
        }
    }

        客户端: client.go

    package main
    
    import (
        "log"
        "net"
    )
    
    func main() {
        for i := 0; i < 40000; i++ {
            conn, err := net.Dial("tcp", "x.x.x.x:5000")
            if err != nil {
                log.Println(err)
                return
            }
        
            go Read(conn)
        }
    
        log.Println("ok")
        select {}
    }
    
    func Read(conn net.Conn) {
        buf := make([]byte, 64)
        for {
            _, err := conn.Read(buf)
            if err != nil {
                log.Println(err)
                return
            }
        }    
    }

    结论:

          开始时,服务器是2核,2G内存, 达到8W连接左右,接受新连接的速度就慢了。后来改成8核,20W连接无压力。

          最终5个客户端,每个客户端发起40000个连接, 共20W连接。
          服务器单进程, 接受20W个连接。CPU,内存压力都很小。

  • 相关阅读:
    背水一战 Windows 10 (90)
    背水一战 Windows 10 (89)
    背水一战 Windows 10 (88)
    背水一战 Windows 10 (87)
    背水一战 Windows 10 (86)
    背水一战 Windows 10 (85)
    背水一战 Windows 10 (84)
    背水一战 Windows 10 (83)
    背水一战 Windows 10 (82)
    背水一战 Windows 10 (81)
  • 原文地址:https://www.cnblogs.com/bear129/p/7919600.html
Copyright © 2011-2022 走看看