rov-server-restart.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #!/bin/env python
  2. # coding=utf-8
  3. import logging
  4. import time
  5. import docker
  6. import sys
  7. import requests
  8. import json
  9. import queue
  10. import threading
  11. from aliyunsdkcore import client
  12. from aliyunsdkecs.request.v20140526.DescribeNetworkInterfacesRequest import DescribeNetworkInterfacesRequest
  13. from aliyunsdkcore.request import CommonRequest
  14. from aliyunsdkslb.request.v20140515.DescribeLoadBalancerAttributeRequest import DescribeLoadBalancerAttributeRequest
  15. from concurrent.futures import ThreadPoolExecutor
  16. logging.basicConfig(level=logging.INFO,
  17. format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
  18. datefmt='%a, %d %b %Y %H:%M:%S')
  19. # ##### 修改负载均衡权限
  20. AccessKey = 'LTAIuPbTPL3LDDKN'
  21. AccessSecret = 'ORcNedKwWuwVtcq4IRFtUDZgS0b1le'
  22. RegionId = 'cn-hangzhou'
  23. clt = client.AcsClient(AccessKey, AccessSecret, RegionId)
  24. slb_id_1 = 'lb-bp1werfophtsjzfr76njm'
  25. def getInstanceId(slb_id):
  26. """获取slb下所有服务器信息"""
  27. request = DescribeLoadBalancerAttributeRequest()
  28. request.set_accept_format('json')
  29. request.set_LoadBalancerId(slb_id)
  30. response = clt.do_action_with_exception(request)
  31. return json.loads(response)
  32. def setWeight(slb_id, instance_id, weight):
  33. """
  34. 设置slb权重
  35. :param slb_id: slb_id
  36. :param instance_id: 服务器id
  37. :param weight: 权重值
  38. :return: None
  39. """
  40. BackendServers = [{"ServerId": instance_id, "Weight": weight}]
  41. request = CommonRequest()
  42. request.set_accept_format('json')
  43. request.set_domain('slb.aliyuncs.com')
  44. request.set_version('2014-05-15')
  45. request.set_method('POST')
  46. request.set_action_name('SetBackendServers')
  47. request.add_query_param('BackendServers', BackendServers)
  48. request.add_query_param('LoadBalancerId', slb_id)
  49. try:
  50. response = clt.do_action_with_exception(request)
  51. except Exception as e:
  52. logging.error(e)
  53. def set_weight_for_more(slb_id, instance_id_list, weight):
  54. """
  55. 同时设置多台服务器的slb权重,权重一样
  56. :param slb_id: slb_id
  57. :param instance_id_list: 服务器id list
  58. :param weight: 权重值
  59. :return: None
  60. """
  61. BackendServers = [{"ServerId": instance_id, "Weight": weight} for instance_id in instance_id_list]
  62. request = CommonRequest()
  63. request.set_accept_format('json')
  64. request.set_domain('slb.aliyuncs.com')
  65. request.set_version('2014-05-15')
  66. request.set_method('POST')
  67. request.set_action_name('SetBackendServers')
  68. request.add_query_param('BackendServers', BackendServers)
  69. request.add_query_param('LoadBalancerId', slb_id)
  70. try:
  71. response = clt.do_action_with_exception(request)
  72. except Exception as e:
  73. logging.error(e)
  74. def getIpadd(instance_id):
  75. """获取实例IP地址"""
  76. request = DescribeNetworkInterfacesRequest()
  77. request.set_accept_format('json')
  78. request.set_InstanceId(instance_id)
  79. response = clt.do_action_with_exception(request)
  80. request_content = json.loads(response)
  81. IpAddr = request_content['NetworkInterfaceSets']['NetworkInterfaceSet'][0]['PrivateIpAddress']
  82. return IpAddr
  83. def checkHealth(ipadd):
  84. """健康检查"""
  85. while True:
  86. health_url = 'http://%s:5001/healthcheck' %(ipadd)
  87. header = {"Content-Type": "application/json"}
  88. try:
  89. health_code = requests.get(health_url).status_code
  90. except Exception as e:
  91. continue
  92. if health_code == 200:
  93. return False
  94. def setInstanceWeightProcess(instance_id):
  95. """服务更新完之后逐步修改服务器的权重值"""
  96. # 直接加载100会出现502。权重值每次增加20,每5s修改一次
  97. for i in range(1, 6):
  98. weight = i * 20
  99. setWeight(slb_id_1, instance_id, weight)
  100. time.sleep(5)
  101. def restart():
  102. """重启服务"""
  103. # 等待60s,处理剩余请求
  104. time.sleep(60)
  105. global success_count, finished_instance_id_list
  106. apps = 'rov-server'
  107. while not q2.empty():
  108. instance_id = q2.get()
  109. ipadd = getIpadd(instance_id)
  110. logging.info(f"服务器信息:{instance_id}/{ipadd}")
  111. client = docker.DockerClient(base_url=f'tcp://{ipadd}:2375', timeout=60)
  112. try:
  113. # 重启容器
  114. id = client.containers.get(apps)
  115. id.restart()
  116. checkHealth(ipadd)
  117. time.sleep(30)
  118. print(f"{ipadd}: 权重修改中......")
  119. # 修改权重
  120. setInstanceWeightProcess(instance_id)
  121. success_count = success_count + 1
  122. finished_instance_id_list.append(instance_id)
  123. print(f"重启进度: {success_count}/{total}")
  124. except Exception as e:
  125. raise e
  126. sys.exit() # 容器启动失败立即退出更新
  127. class MyThread(threading.Thread):
  128. def __init__(self, func):
  129. threading.Thread.__init__(self)
  130. self.func = func
  131. def run(self):
  132. self.func()
  133. if __name__ == '__main__':
  134. # 更新完成计数
  135. success_count = 0
  136. threads = []
  137. # 线程数
  138. thread_num = 1
  139. # 获取slb下所有服务器信息
  140. res = getInstanceId(slb_id_1)
  141. # slb下服务器总数
  142. total = len(res["BackendServers"]["BackendServer"])
  143. q1 = queue.Queue()
  144. q2 = queue.Queue()
  145. # 获取slb下所有服务器的 instance_id
  146. if res["BackendServers"]["BackendServer"]:
  147. for i in range((len(res["BackendServers"]["BackendServer"]))):
  148. instance_id = res["BackendServers"]["BackendServer"][i]["ServerId"]
  149. q1.put(instance_id)
  150. while not q1.empty():
  151. # 摘流量
  152. for i in range(thread_num):
  153. if q1.empty():
  154. break
  155. instance_id = q1.get()
  156. # 设置slb权重为0
  157. setWeight(slb_id_1, instance_id, 0)
  158. q2.put(instance_id)
  159. time.sleep(5)
  160. # 挂流量
  161. finished_instance_id_list = []
  162. for i in range(thread_num):
  163. # 开启线程
  164. thread = MyThread(restart)
  165. thread.start()
  166. threads.append(thread)
  167. for thread in threads:
  168. thread.join()
  169. # 权重补充(一秒内同时请求两个服务器修改权重,可能会有一个失败)
  170. print(finished_instance_id_list)
  171. set_weight_for_more(slb_id=slb_id_1, instance_id_list=finished_instance_id_list, weight=100)