menu arrow_back 湛蓝安全空间 |狂野湛蓝,暴躁每天 chevron_right All_wiki chevron_right the-way-to-go_ZH_CN chevron_right eBook chevron_right 14.15.md
  • home 首页
  • brightness_4 暗黑模式
  • cloud
    xLIYhHS7e34ez7Ma
    cloud
    湛蓝安全
    code
    Github
    14.15.md
    2.23 KB / 2024-07-16 23:14:28
        # 14.15 漏桶算法
    
    (译者注:翻译遵照原文,但是对于完全没听过这个算法的人来说比较晦涩,请配合代码片段理解)
    
    考虑以下的客户端-服务器结构:客户端协程执行一个无限循环从某个源头(也许是网络)接收数据;数据读取到 `Buffer` 类型的缓冲区。为了避免分配过多的缓冲区以及释放缓冲区,它保留了一份空闲缓冲区列表,并且使用一个缓冲通道来表示这个列表:`var freeList = make(chan *Buffer,100)`
    
    这个可重用的缓冲区队列 (`freeList`) 与服务器是共享的。 当接收数据时,客户端尝试从 `freeList` 获取缓冲区;但如果此时通道为空,则会分配新的缓冲区。一旦消息被加载后,它将被发送到服务器上的 `serverChan` 通道:
    
    ```go
    var serverChan = make(chan *Buffer)
    ```
    
    以下是客户端的算法代码:
    
    ```go
    func client() {
       for {
           var b *Buffer
           // Grab a buffer if available; allocate if not 
           select {
               case b = <-freeList:
                   // Got one; nothing more to do
               default:
                   // None free, so allocate a new one
                   b = new(Buffer)
           }
           loadInto(b)         // Read next message from the network
           serverChan <- b     // Send to server
           
       }
    }
    ```
    
    服务器的循环则接收每一条来自客户端的消息并处理它,之后尝试将缓冲返回给共享的空闲缓冲区:
    
    ```go
    func server() {
        for {
            b := <-serverChan       // Wait for work.
            process(b)
            // Reuse buffer if there's room.
            select {
                case freeList <- b:
                    // Reuse buffer if free slot on freeList; nothing more to do
                default:
                    // Free list full, just carry on: the buffer is 'dropped'
            }
        }
    }
    ```
    
    但是这种方法在 `freeList` 通道已满的时候是行不通的,因为无法放入空闲 `freeList` 通道的缓冲区会被“丢到地上”由垃圾收集器回收(故名:漏桶算法)。
    
    
    ## 链接
    
    - [目录](directory.md)
    - 上一节:[并行化大量数据的计算](14.14.md)
    - 下一节:[对 Go 协程进行基准测试](14.16.md)
    
    
    links
    file_download