负载均衡算法-轮询、加权轮询、源地址hash、一致性hash
1.轮询算法
根据服务ip列表元素进行依次访问
代码:
server_ip_list = ["192.168.1.10", "192.168.1.20", "192.168.1.30", "192.168.1.40"] def get_ip(): for server_ip in server_ip_list: print(server_ip) # 循环执行get_ip()函数1次,查看输出结果 for i in range(1): get_ip()
2.加权轮询算法
根据服务ip列表元素+权重值进行轮询访问
经典加权轮询算法
python代码:
dict = {"192.168.1.10":{'weight':5,'dynamicWeight':0}, "192.168.2.20":{'weight':1,'dynamicWeight':0}, "192.168.3.30":{'weight':3,'dynamicWeight':0}, "192.168.4.40":{'weight':2,'dynamicWeight':0}} def get_ip(): # 初始化总权重 total_weight = 0 # 求总权重值 for k,v in dict.items(): total_weight += v['weight'] # 求每个服务器ip的动态权重值 for k,v in dict.items(): v['dynamicWeight'] += v['weight'] # 比较动态权重值,最大的动态权重值的妃嫔打印出来 dw = 0 ps = '' for k,v in dict.items(): if v['dynamicWeight'] > dw: dw = v['dynamicWeight'] ps = k dict[ps]['dynamicWeight'] = dw - total_weight print(ps) # 循环执行get_princess()函数11次,查看输出结果 for i in range(11): get_ip()
3.源地址hash算法
根据客户端ip地址的hash值 % 服务端ip的数量 得到的值作为服务端ip列表的索引值
这种算法缺点:一台服务器节点故障,会引起所有客户端连接服务发生变化。
python代码:import hashlib
server_ip_list = ["192.168.1.10", "192.168.2.20", "192.168.3.30", "192.168.4.40"] client_ip_list = ["113.88.97.173", "106.11.154.33", "207.46.13.149","42.156.137.120", "203.208.60.0", "119.39.47.182", "171.34.179.4", "111.175.58.52", "124.235.138.199","175.184.166.184","175.184.166.18"] def get_ip(): hash_list = [] for clientip in client_ip_list: #print(hash(str(clientip))) m = hashlib.md5() m.update(str(clientip).encode('utf-8')) hash_list.append(m.hexdigest()) #print(hash_list)
# python的hash()无法获取不变的值,只能用这种hash方法代替
index = len(hash_list) % len(server_ip_list) print(clientip + '请求的服务器ip为:'+ server_ip_list[index]) for i in range(1): get_ip()
4.一致性hash算法
解决”一台服务器节点故障,会引起所有客户端连接服务发生变化。”,当一台服务器发生故障时,只影响连接到这台服务的客户端ip,其他客户端不受影响。
原理:通过将服务ip添加多个虚拟节点hash值,将客户端ip的hash值与虚拟节点hash值做比较,根据客户端ip所在的范围,进行分配服务ip给客户端使用
python代码:
import hashlib server_ip_list = ["192.168.1.10", "192.168.2.20", "192.168.3.30","192.168.4.40"] client_ip_list = ["113.88.97.173", "106.11.154.33", "207.46.13.149","42.156.137.120", "203.208.60.0", "119.39.47.182", "171.34.179.4", "111.175.58.52", "124.235.138.199","175.184.166.184","111.175.58.52", "124.235.18.119","175.144.163.124","175.14.166.114","111.175.8.152", "124.23.18.113","175.144.13.116"] def get_md5(data): m = hashlib.md5() m.update(data.encode('utf-8')) return m.hexdigest() def get_ip(): virtual_nodes = 500 node_dict = {} # 遍历服务器ip,生成对应的虚拟结点 for serverip in server_ip_list: for i in range(virtual_nodes): # serverip加上一些动态参数生成md5值 hash_key = get_md5(str('{0}VN{1}'.format(serverip,i))) node_dict[hash_key]=serverip # 将node_dict字典按key排序生成列表 sorted_key_list = sorted(node_dict) # 将node_dict字典按key排序 node_dict = sorted(node_dict.items(),key=lambda d:d[0],reverse=False) #print(node_dict) #print(sorted_key_list) for clientip in client_ip_list: selected_key_list = [] # clientip生成md5值 hc = get_md5(str(clientip)) #print(hc) switch = 0 for key in sorted_key_list: #print(key) # clientip和sorted_key_list中的md5值做比较,clientip的md5值小于等于sorted_key_list中的md5值,switch=1 if hc <= key: selected_key_list.append(key) switch=1 if switch == 0: firstkey = sorted_key_list[0] else: firstkey = selected_key_list[0] #print(firstkey) #print(selected_key_list) print("{0}请求的服务器ip为:{1}".format(clientip,dict(node_dict)[firstkey])) # for i in range(2): get_ip()