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,内存压力都很小。

  • 相关阅读:
    AngularJS自定义表单验证器
    AngularJS自定义表单验证
    DataTables自定义筛选器
    DataTables列过滤器
    DataTables语言国际化
    DataTables DOM定位
    DataTables自定义事件
    DataTables给表格绑定事件
    自定义Celery任务记录器
    celery 日志设置
  • 原文地址:https://www.cnblogs.com/bear129/p/7919600.html
Copyright © 2011-2022 走看看