Browse Source

add rov-server && update

liqian 2 years ago
parent
commit
d5c835500d

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 8 - 0
.idea/deploy.iml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="PYTHON_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 16 - 0
.idea/inspectionProfiles/Project_Default.xml

@@ -0,0 +1,16 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="ignoredPackages">
+        <value>
+          <list size="2">
+            <item index="0" class="java.lang.String" itemvalue="psycopg2" />
+            <item index="1" class="java.lang.String" itemvalue="aliyun_python_sdk" />
+          </list>
+        </value>
+      </option>
+    </inspection_tool>
+    <inspection_tool class="SqlNoDataSourceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
+  </profile>
+</component>

+ 6 - 0
.idea/inspectionProfiles/profiles_settings.xml

@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+  <settings>
+    <option name="USE_PROJECT_PROFILE" value="false" />
+    <version value="1.0" />
+  </settings>
+</component>

+ 4 - 0
.idea/misc.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8" project-jdk-type="Python SDK" />
+</project>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/deploy.iml" filepath="$PROJECT_DIR$/.idea/deploy.iml" />
+    </modules>
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>

+ 3 - 0
rov-sever/client/rov-server-start.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+docker login --username=stuuudys --password=Qingqu@2019   registry-vpc.cn-hangzhou.aliyuncs.com
+docker run  -d -it   --network=host  --name=rov-server   registry-vpc.cn-hangzhou.aliyuncs.com/stuuudy/rov-server:latest                                                                                                                                                         

+ 195 - 0
rov-sever/server/ess-instance-rov-server.py

@@ -0,0 +1,195 @@
+# #!/usr/bin/env python
+# #coding=utf-8
+
+import json
+import logging
+import time
+import requests
+import sys
+from aliyunsdkcore import client
+from aliyunsdkcore.client import AcsClient
+from aliyunsdkcore.acs_exception.exceptions import ClientException
+from aliyunsdkcore.acs_exception.exceptions import ServerException
+from aliyunsdkecs.request.v20140526.CreateInstanceRequest import CreateInstanceRequest
+from aliyunsdkecs.request.v20140526.StartInstanceRequest import StartInstanceRequest
+from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest
+from aliyunsdkecs.request.v20140526.RunInstancesRequest import RunInstancesRequest
+from aliyunsdkecs.request.v20140526.DescribeNetworkInterfacesRequest import DescribeNetworkInterfacesRequest
+from aliyunsdkslb.request.v20140515.AddBackendServersRequest import AddBackendServersRequest
+from aliyunsdkecs.request.v20140526.RunCommandRequest import RunCommandRequest
+
+logging.basicConfig(level=logging.INFO,
+                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
+                    datefmt='%a, %d %b %Y %H:%M:%S')
+# ##### 购买服务器权限
+# access key Id
+ak_id = "LTAI4GBWbFvvXoXsSVBe1o9f"
+# access key secret
+ak_secret = "kRAikWitb4kDxaAyBqNrmLmllMEDO3"
+# 设置地域
+region_id = "cn-hangzhou"
+clt = client.AcsClient(ak_id, ak_secret, region_id)
+
+# 获取批量创建ECS实例的数量, 取值范围:1-100, 默认值:1
+amount = int(sys.argv[1])
+# 使用的镜像信息
+image_id = "m-bp13xpsku1wo7qzic7zl"
+
+# 设置实例规格
+instance_type = "ecs.ic5.large"
+# 选择的交换机
+vswitch_id = "vsw-bp19lpjwtc6j0p0m9mdc2"
+# 当前VPC类型的安全组
+security_group_id = "sg-bp1irhrkr4vfj272hk4y"
+# 硬盘的大小,单位:G
+disk_size = "200"
+# 服务器命名
+instance_name = "ESS-rov-server-[1,2]"
+# 服务器所在区域
+zone_id = "cn-hangzhou-h"
+# 磁盘类型:云盘
+disk_category = "cloud_efficiency"
+# 密钥
+key_pair_name = "stuuudy"
+# 负载均衡ID
+slb_id_2 = "lb-bp1werfophtsjzfr76njm"
+
+# ##### 修改负载均衡权限
+AccessKey = 'LTAIuPbTPL3LDDKN'
+AccessSecret = 'ORcNedKwWuwVtcq4IRFtUDZgS0b1le'
+RegionId = 'cn-hangzhou'
+client = AcsClient(AccessKey, AccessSecret, RegionId)
+
+
+def build_request():
+    """购买服务器参数配置"""
+    request = RunInstancesRequest()
+    request.set_ImageId(image_id)
+    request.set_VSwitchId(vswitch_id)
+    request.set_SecurityGroupId(security_group_id)
+    request.set_ZoneId(zone_id)
+    request.set_InstanceType(instance_type)
+    # request.set_UserData(init_data)
+    request.set_InstanceName(instance_name)
+    request.set_SystemDiskSize(disk_size)
+    request.set_SystemDiskCategory(disk_category)
+    request.set_KeyPairName(key_pair_name)
+    request.set_Tags([
+      {
+        "Key": "app",
+        "Value": "rov-server"
+      }
+    ])
+    return request
+
+
+def _send_request(request):
+    """发送API请求"""
+    request.set_accept_format('json')
+    try:
+        response_str = clt.do_action_with_exception(request)
+        logging.info(response_str)
+        response_detail = json.loads(response_str)
+        return response_detail
+    except Exception as e:
+        logging.error(e)
+
+
+def check_instance_running(instance_ids):
+    """检查服务器运行状态"""
+    request = DescribeInstancesRequest()
+    request.set_InstanceIds(json.dumps(instance_ids))
+    response = _send_request(request)
+    if response.get('Code') is None:
+        instances_list = response.get('Instances').get('Instance')
+        running_count = 0
+        for instance_detail in instances_list:
+            if instance_detail.get('Status') == "Running":
+                running_count += 1
+        return running_count
+
+
+def runCommand(instance_ids):
+    """批量执行shell脚本:启动服务"""
+    request = RunCommandRequest()
+    request.set_accept_format('json')
+    request.set_Type("RunShellScript")
+    request.set_CommandContent("sh  /home/sh/rov-server-start.sh")
+    request.set_InstanceIds(instance_ids)
+    response = clt.do_action_with_exception(request)
+    logging.info(response)
+
+
+def healthCheck(instance_id):
+    """服务健康检查 & 服务器挂载到负载均衡"""
+    ipaddr = getIpaddr(instance_id)
+    while True:
+        health_url = 'http://%s:5001/healthcheck' %(ipaddr)
+        try:
+            http_code = requests.get(health_url).status_code
+        except:
+            logging.info("images is downloading")
+            http_code = 0
+
+        if http_code == 200:
+            break
+        else:
+            time.sleep(20)
+
+    # 服务预热60s, 服务刚启动时CPU很高
+    time.sleep(60)
+    # 挂载到负载均衡
+    addBackendServers(slb_id_2, instance_id)
+
+
+def addBackendServers(slb_id, instance_id):
+    """服务器挂载到负载均衡"""
+    request = AddBackendServersRequest()
+    request.set_accept_format('json')
+    ipaddr = getIpaddr(instance_id)
+    request.set_LoadBalancerId(slb_id)
+
+    request.set_BackendServers([{"ServerId": instance_id, "Weight": "100", "Type": "ecs", "ServerIp": ipaddr}])
+    response = client.do_action_with_exception(request)
+    logging.info(response)
+
+
+def getIpaddr(instance_id):
+    """根据 instance_id 获取实例IP地址"""
+    request = DescribeNetworkInterfacesRequest()
+    request.set_accept_format('json')
+    request.set_InstanceId(instance_id)
+    response = clt.do_action_with_exception(request)
+    request_content = json.loads(response)
+    ipaddr = request_content['NetworkInterfaceSets']['NetworkInterfaceSet'][0]['PrivateIpAddress']
+    return ipaddr
+
+
+def _execute_request(request):
+    response = _send_request(request)
+    if response.get('Code') is None:
+        instance_ids = response.get('InstanceIdSets').get('InstanceIdSet')
+        running_amount = 0
+        while running_amount < amount:
+            time.sleep(10)
+            running_amount = check_instance_running(instance_ids)
+
+        logging.info(f"{instance_ids} is running")
+        time.sleep(60)
+        runCommand(instance_ids)
+
+        for instance_id in instance_ids:
+            healthCheck(instance_id)
+
+
+def create_multiple_instances():
+    """创建ECS实例并启动"""
+    request = build_request()
+    request.set_Amount(amount)
+    _execute_request(request)
+
+
+if __name__ == '__main__':
+    logging.info("Start Create Instances")
+    # 创建ECS实例并启动
+    create_multiple_instances()

+ 244 - 0
rov-sever/server/rov-server-update.py

@@ -0,0 +1,244 @@
+#!/bin/env python
+# coding=utf-8
+import logging
+import time
+import docker
+import sys
+import requests
+import json
+import queue
+import threading
+from aliyunsdkcore import client
+from aliyunsdkecs.request.v20140526.DescribeNetworkInterfacesRequest import DescribeNetworkInterfacesRequest
+from aliyunsdkcore.request import CommonRequest
+from aliyunsdkslb.request.v20140515.DescribeLoadBalancerAttributeRequest import DescribeLoadBalancerAttributeRequest
+from concurrent.futures import ThreadPoolExecutor
+
+logging.basicConfig(level=logging.INFO,
+                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
+                    datefmt='%a, %d %b %Y %H:%M:%S')
+
+# ##### 修改负载均衡权限
+AccessKey = 'LTAIuPbTPL3LDDKN'
+AccessSecret = 'ORcNedKwWuwVtcq4IRFtUDZgS0b1le'
+RegionId = 'cn-hangzhou'
+clt = client.AcsClient(AccessKey, AccessSecret, RegionId)
+
+slb_id_1 = 'lb-bp1werfophtsjzfr76njm'
+
+
+def getInstanceId(slb_id):
+    """获取slb下所有服务器信息"""
+    request = DescribeLoadBalancerAttributeRequest()
+    request.set_accept_format('json')
+    request.set_LoadBalancerId(slb_id)
+    response = clt.do_action_with_exception(request)
+    return json.loads(response)
+
+
+def setWeight(slb_id, instance_id, weight):
+    """
+    设置slb权重
+    :param slb_id: slb_id
+    :param instance_id: 服务器id
+    :param weight: 权重值
+    :return: None
+    """
+    BackendServers = [{"ServerId": instance_id, "Weight": weight}]
+    request = CommonRequest()
+    request.set_accept_format('json')
+    request.set_domain('slb.aliyuncs.com')
+    request.set_version('2014-05-15')
+    request.set_method('POST')
+    request.set_action_name('SetBackendServers')
+    request.add_query_param('BackendServers', BackendServers)
+    request.add_query_param('LoadBalancerId', slb_id)
+    try:
+        response = clt.do_action_with_exception(request)
+    except Exception as e:
+        logging.error(e)
+
+
+def getIpadd(instance_id):
+    """获取实例IP地址"""
+    request = DescribeNetworkInterfacesRequest()
+    request.set_accept_format('json')
+    request.set_InstanceId(instance_id)
+    response = clt.do_action_with_exception(request)
+    request_content = json.loads(response)
+    IpAddr = request_content['NetworkInterfaceSets']['NetworkInterfaceSet'][0]['PrivateIpAddress']
+    return IpAddr
+
+
+def checkHealth(ipadd):
+    """健康检查"""
+    while True:
+        health_url = 'http://%s:5001/healthcheck' %(ipadd)
+        header = {"Content-Type": "application/json"}
+        try:
+            health_code = requests.get(health_url).status_code
+        except Exception as e:
+           continue
+        if health_code == 200:
+            return False
+
+
+def setInstanceWeightProcess(instance_id):
+    """服务更新完之后逐步修改服务器的权重值"""
+    # 直接加载100会出现502。权重值每次增加20,每5s修改一次
+    for i in range(1, 6):
+        weight = i * 20
+        setWeight(slb_id_1, instance_id, weight)
+        time.sleep(5)
+
+
+# def update():
+#     """更新服务"""
+#     time.sleep(10)
+#     global success_count
+#     apps = 'rov-server'
+#     version = sys.argv[1]
+#     registry = 'registry-vpc.cn-hangzhou.aliyuncs.com/stuuudy/rov-server:{}'.format(version)
+#     while not q2.empty():
+#         instance_id = q2.get()
+#         ipadd = getIpadd(instance_id)
+#         logging.info(f"服务器信息:{instance_id}/{ipadd}")
+#         client = docker.DockerClient(base_url=f'tcp://{ipadd}:2375', timeout=60)
+#         try:
+#             # 更新前移除旧的容器
+#             id = client.containers.get(apps)
+#             id.remove(force=True)
+#         except Exception as e:
+#             print("容器不存在或者无法删除当前容器")
+#
+#         try:
+#             # 更新前删除旧的镜像
+#             images = client.images.list(all)
+#             for i in range(len(images)):
+#                 if images[i]:
+#                     client.images.remove(force=True, image=images[i].tags[0])
+#                     time.sleep(2)
+#             # images = client.images.get(registry)
+#             # client.images.remove(force=True, image=registry)
+#         except Exception as e:
+#             print(e)
+#             print("镜像不存在,无法获取到镜像ID")
+#             sys.exit(0)
+#
+#         try:
+#             # 登录镜像仓库
+#             client.login(username='stuuudys', password='Qingqu@2019', registry='registry-vpc.cn-hangzhou.aliyuncs.com')
+#             # 启动一个容器
+#             client.containers.run(registry, detach=True, cap_add='SYS_PTRACE', network_mode='host', name=apps,
+#                                   volumes={'/datalog/': {'bind': '/datalog/', 'mode': 'rw'}})
+#             checkHealth(ipadd)
+#             print(f"{ipadd}: 权重修改中......")
+#             # 修改权重
+#             setInstanceWeightProcess(instance_id)
+#             success_count = success_count + 1
+#             print(f"更新进度: {success_count}/{total}")
+#         except Exception as e:
+#             raise e
+#             sys.exit()  # 容器启动失败立即退出更新
+
+
+class MyThread(threading.Thread):
+    def __init__(self, func):
+        threading.Thread.__init__(self)
+        self.func = func
+
+    def run(self):
+        self.func()
+
+
+def update_sever(instance_id):
+    """更新服务"""
+    # time.sleep(20)
+    # print(slb_id_1, instance_id)
+
+    # 设置slb权重为0
+    setWeight(slb_id_1, instance_id, 0)
+    # 等待10s,处理剩余请求
+    time.sleep(10)
+
+    apps = 'rov-server'
+    version = sys.argv[1]
+    registry = f'registry-vpc.cn-hangzhou.aliyuncs.com/stuuudy/rov-server:{version}'
+    ipadd = getIpadd(instance_id)
+    logging.info(f"服务器信息:{instance_id}/{ipadd}")
+    client = docker.DockerClient(base_url=f'tcp://{ipadd}:2375', timeout=60)
+    try:
+        # 更新前移除旧的容器
+        id = client.containers.get(apps)
+        id.remove(force=True)
+    except Exception as e:
+        print("容器不存在或者无法删除当前容器")
+
+    try:
+        # 更新前删除旧的镜像
+        images = client.images.list(all)
+        for i in range(len(images)):
+            if images[i]:
+                client.images.remove(force=True, image=images[i].tags[0])
+                time.sleep(2)
+        # images = client.images.get(registry)
+        # client.images.remove(force=True, image=registry)
+    except Exception as e:
+        print(e)
+        print("镜像不存在,无法获取到镜像ID")
+        sys.exit(0)
+
+    try:
+        # 登录镜像仓库
+        client.login(username='stuuudys', password='Qingqu@2019', registry='registry-vpc.cn-hangzhou.aliyuncs.com')
+        # 启动一个容器
+        client.containers.run(registry, detach=True, cap_add='SYS_PTRACE', network_mode='host', name=apps,
+                              volumes={'/datalog/': {'bind': '/datalog/', 'mode': 'rw'}})
+        checkHealth(ipadd)
+        print(f"{ipadd}: 权重修改中......")
+        # 修改权重
+        setInstanceWeightProcess(instance_id)
+    except Exception as e:
+        raise e
+        sys.exit()  # 容器启动失败立即退出更新
+
+
+if __name__ == '__main__':
+    # 更新完成计数
+    success_count = 0
+    threads = []
+    # 线程数
+    thread_num = 2
+    # 获取slb下所有服务器信息
+    res = getInstanceId(slb_id_1)
+    # slb下服务器总数
+    total = len(res["BackendServers"]["BackendServer"])
+    # q1 = queue.Queue()
+    # q2 = queue.Queue()
+    thread_pool = ThreadPoolExecutor(max_workers=thread_num)
+    # 获取slb下所有服务器的 instance_id
+    if res["BackendServers"]["BackendServer"]:
+        for i in range((len(res["BackendServers"]["BackendServer"]))):
+            instance_id = res["BackendServers"]["BackendServer"][i]["ServerId"]
+            # q1.put(instance_id)
+            thread_pool.submit(update_sever, instance_id)
+    thread_pool.shutdown(wait=True)
+
+    # while not q1.empty():
+    #     # 摘流量
+    #     for i in range(thread_num):
+    #         if q1.empty():
+    #             break
+    #         instance_id = q1.get()
+    #         # 设置slb权重为0
+    #         setWeight(slb_id_1, instance_id, 0)
+    #         q2.put(instance_id)
+    #
+    #     # 挂流量
+    #     for i in range(thread_num):
+    #         # 开启线程
+    #         thread = MyThread(update)
+    #         thread.start()
+    #         threads.append(thread)
+    #     for thread in threads:
+    #         thread.join()