这两个函数是负载均衡模块最底层的函数,负责实际获取一个连接和回收一个连接的预备操作。之所以说是预备操作,是因为在这两个函数中,并不实际进行建立连接或者释放连接的动作,而只是执行获取连接的地址或维护连接状态的操作。需要理解的清楚一点,在peer.get函数中获取连接的地址信息,并不代表这时连接一定没有被建立,相反的,通过get函数的返回值,nginx可以了解是否存在可用连接,连接是否已经建立。这些返回值总结如下: | 返回值 | 说明 | nginx后续动作 | |-----|-----|-----| | NGX_DONE | 得到了连接地址信息,并且连接已经建立。 | 直接使用连接,发送数据。 | | NGX_OK | 得到了连接地址信息,但连接并未建立。 | 建立连接,如连接不能立即建立,设置事件, 暂停执行本请求,执行别的请求。 | | NGX_BUSY | 所有连接均不可用。 | 返回502错误至客户端。 | 各位读者看到上面这张表,可能会有几个问题浮现出来: | Q: | 什么时候连接是已经建立的? | |-----|-----| | A: | 使用后端keepalive连接的时候,连接在使用完以后并不关闭,而是存放在一个队列中,新的请求只需要从队列中取出连接,这些连接都是已经准备好的。 | | Q: | 什么叫所有连接均不可用? | | A: | 初始化请求的过程中,建立了一张表,get函数负责每次从这张表中不重复的取出一个连接,当无法从表中取得一个新的连接时,即所有连接均不可用。 | | Q: | 对于一个请求,peer.get函数可能被调用多次么? | | A: | 正式如此。当某次peer.get函数得到的连接地址连接不上,或者请求对应的服务器得到异常响应,nginx会执行ngx_http_upstream_next,然后可能再次调用peer.get函数尝试别的连接。upstream整体流程如下: | ![](https://box.kancloud.cn/2015-08-12_55cb06b225224.PNG)