## 负载均衡
相信负载均衡这个话题基本已经深入每个做微服务开发或设计者的人心,负载均衡的实现有硬件和软件,硬件有F5,A10等机器,软件有LVS,nginx,HAProxy等等,负载均衡的算法有 random , RoundRobin , ConsistentHash等等。
### Nginx负载均衡故障转移
**转移流程**
nginx 根据给定好的负载均衡算法进行调度,当请求到tomcat1,nginx发现tomcat1出现连接错误(节点失效),nginx会根据一定的机制将tomcat1从调用的负载列表中清除,在下一次请求,nginx不会分配请求到有问题的tomcat1上面,会将请求转移到其他的tomcat之上。
**节点失效**
nginx默认判断节点失效是以connect refuse和timeout为标准,在对某个节点进行fails累加,当fails大于max_fails时,该节点失效。
**节点恢复**
当某个节点失败的次数大于max_fails时,但不超过fail_timeout,nginx将不在对该节点进行探测,直到超过失效时间或者所有的节点都失效,nginx会对节点进行重新探测。
### ZK负载均衡故障转移
在使用ZK作为注册中心时,故障的发现是由Zk去进行发现,业务逻辑层通过watch的心跳机制将自己注册到zk上,网关对zk进行订阅就可以知道有多少可以调用的列表。当业务逻辑层在重启或者被关闭时就会跟zk断了心跳,zk会更新可调用列表。
使用zk作为负载均衡的协调器,最大的问题是zk对于服务是否可用是基于pingpong的方式,只要服务心跳存在,zk就认为服务是处在于可用状态,但是服务如果处在于假死的状态,zk是无从得知的。这个时候,业务逻辑服务是否真正可用只能够由网关知道。
**幂等设计**
为何会牵出幂等设计的问题,主要是因为负载均衡的failover策略,就是对失败的服务会进行重试,一般来说,如果是读操作的服务,重复执行也不会出问题,但想象一下,如果是一个创建订单减库存的操作,第一次调用也tomcat1超时,再重新调用了tomcat2,这个时候我们都不能确认超时调用的tomcat1是否真的被调用,有可能根本就调用不成功,有可能已经调用成功但是因为某些原因返回超时而已,所以,很大程度这个接口会被调用2次。如果我们没有保证幂等性,就有可能一个订单导致了减少2次的库存。所谓的幂等性,就是得保证在同一个业务中,一个接口被调用了多次,其导致的结果都是一样的。