11 Commits 0fbfc736dd ... df70c02eeb

Tác giả SHA1 Thông báo Ngày
  xuekailun df70c02eeb merge 11 tháng trước cách đây
  xuekailun 8ecba954ce update config 11 tháng trước cách đây
  xuekailun 6329a2d3b3 update cloud_essd 11 tháng trước cách đây
  xuekailun ef2e2da499 update slb > clb 11 tháng trước cách đây
  xuekailun 05280b8100 add commonapi_reduce_with_count 11 tháng trước cách đây
  xuekailun aa661259c1 add clb_utils.py 11 tháng trước cách đây
  xuekailun 76a300ac2b add commonapi_scaling_h_count 11 tháng trước cách đây
  xuekailun 9a842d70a9 add commonapi_start.sh 11 tháng trước cách đây
  xuekailun b6ad13a8b0 add commonapi_config 11 tháng trước cách đây
  xuekailun 0e35473190 update config test 11 tháng trước cách đây
  xuekailun 0b429d8f5d del file_content log 11 tháng trước cách đây

+ 524 - 0
commonapi/clb_utils.py

@@ -0,0 +1,524 @@
+import logging
+import json
+import sys
+import time
+import requests
+import asyncio
+
+from aliyunsdkcore.client import AcsClient
+from aliyunsdkslb.request.v20140515.AddBackendServersRequest import AddBackendServersRequest
+from aliyunsdkslb.request.v20140515.RemoveBackendServersRequest import RemoveBackendServersRequest
+from aliyunsdkecs.request.v20140526.RunInstancesRequest import RunInstancesRequest
+from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest
+from aliyunsdkecs.request.v20140526.DescribeNetworkInterfacesRequest import DescribeNetworkInterfacesRequest
+from aliyunsdkslb.request.v20140515.DescribeLoadBalancerAttributeRequest import DescribeLoadBalancerAttributeRequest
+from aliyunsdkecs.request.v20140526.RunCommandRequest import RunCommandRequest
+from aliyunsdkecs.request.v20140526.SendFileRequest import SendFileRequest
+from aliyunsdkecs.request.v20140526.StopInstancesRequest import StopInstancesRequest
+from aliyunsdkecs.request.v20140526.DeleteInstancesRequest import DeleteInstancesRequest
+from aliyunsdkecs.request.v20140526.DescribeInstanceStatusRequest import DescribeInstanceStatusRequest
+from aliyunsdkcore.request import CommonRequest
+
+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')
+
+
+def send_msg_to_feishu(webhook, key_word, msg_text):
+    """发送消息到飞书"""
+    headers = {'Content-Type': 'application/json'}
+    payload_message = {
+        "msg_type": "text",
+        "content": {
+            "text": '{}: {}'.format(key_word, msg_text)
+        }
+    }
+    response = requests.request('POST', url=webhook, headers=headers, data=json.dumps(payload_message))
+    logging.info(response.text)
+
+
+def connect_client(access_key_id, access_key_secret, region_id):
+    """
+    初始化账号,连接客户端
+    :param access_key_id: access key Id, type-string
+    :param access_key_secret: access key secret, type-string
+    :param region_id: region_id
+    :return: clt
+    """
+    try:
+        clt = AcsClient(ak=access_key_id, secret=access_key_secret, region_id=region_id)
+        return clt
+    except Exception as e:
+        # 失败,记录报错信息,发送通知,停止并退出
+        logging.error(e)
+        sys.exit()
+
+
+def build_create_instances_request(image_id, vswitch_id, security_group_id, zone_id, instance_type, instance_name,
+                                   disk_size, disk_category, key_pair_name, tags):
+    """
+    购买服务器参数配置
+    :param image_id: 使用的镜像信息 type-string
+    :param vswitch_id: 选择的交换机 type-string
+    :param security_group_id: 当前vpc类型的安全组 type-string
+    :param zone_id: 服务器所在区域 type-string
+    :param instance_type: 实例规格 type-string
+    :param instance_name: 实例命名 type-string
+    :param disk_size: 磁盘大小,单位:G,type-string
+    :param disk_category: 磁盘类型 type-string
+    :param key_pair_name: 密钥对名称 type-string
+    :param tags: 标签 type-list, eg: [{"Key": "ecs", "Value": "rov-server.prod"}, ...]
+    :return: 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_InstanceName(instance_name)
+    request.set_SystemDiskSize(disk_size)
+    request.set_SystemDiskCategory(disk_category)
+    request.set_KeyPairName(key_pair_name)
+    request.set_Tags(tags)
+    return request
+
+
+def send_request(client, request):
+    """
+    发送API请求
+    :param client: 客户端连接
+    :param request: 请求配置
+    :return: response
+    """
+    request.set_accept_format('json')
+    try:
+        response = client.do_action_with_exception(request)
+        response = json.loads(response)
+        # logging.info(response)
+        return response
+    except Exception as e:
+        # 失败,记录报错信息,发送通知,停止并退出
+        logging.error(e)
+        sys.exit()
+
+
+def send_req(client, request):
+    """
+    发送API请求
+    :param client: 客户端连接
+    :param request: 请求配置
+    :return: response
+    """
+    request.set_accept_format('json')
+    response = client.do_action_with_exception(request)
+    #print(response)
+    response = json.loads(response)
+    print(response)
+        # logging.info(response)
+    print(response.get('Code'))
+    return response
+    #except Exception as e:
+        # 失败,记录报错信息,发送通知,停止并退出
+    #logging.error(e)
+    #sys.exit()
+
+def check_instance_running(client, instance_ids):
+    """
+    检查服务器运行状态
+    :param client: 客户端连接
+    :param instance_ids: 实例id列表, type-list
+    :return: running_count,Status为Running的实例数
+    """
+    try:
+        request = DescribeInstancesRequest()
+        request.set_InstanceIds(json.dumps(instance_ids))
+        request.set_PageSize(100)
+        response = send_request(client=client, request=request)
+        if response.get('Code') is None:
+            instances_list = response.get('Instances').get('Instance')
+            running_count = 0
+            running_instances = []
+            for instance_detail in instances_list:
+                if instance_detail.get('Status') == "Running":
+                    running_count += 1
+                    running_instances.append(instance_detail.get('InstanceId'))
+            return running_count, running_instances
+        else:
+            # 失败,记录报错信息,发送通知,停止并退出
+            logging.error(response)
+            sys.exit()
+    except Exception as e:
+        # 失败,记录报错信息,发送通知,停止并退出
+        logging.error(e)
+        sys.exit()
+
+
+def create_multiple_instances(amount, client,
+                              image_id, vswitch_id, security_group_id, zone_id, instance_type, instance_name,
+                              disk_size, disk_category, key_pair_name, tags):
+    """
+    创建多个ECS实例
+    :param amount: 创建实例数 type-int 取值范围:[1, 100]
+    :param client: 购买机器客户端连接
+    :param image_id: 使用的镜像信息 type-string
+    :param vswitch_id: 选择的交换机 type-string
+    :param security_group_id: 当前vpc类型的安全组 type-string
+    :param zone_id: 服务器所在区域 type-string
+    :param instance_type: 实例规格 type-string
+    :param instance_name: 实例命名 type-string
+    :param disk_size: 磁盘大小,单位:G,type-string
+    :param disk_category: 磁盘类型 type-string
+    :param key_pair_name: 密钥对名称 type-string
+    :param tags: 标签 type-list, eg: [{"Key": "ecs", "Value": "rov-server.prod"}, ...]
+    :return:
+    """
+    logging.info(f"create instances start, request amount: {amount}.")
+    # 1. 连接客户端
+    # create_instances_clt = connect_client(
+    #     access_key_id=access_key_id, access_key_secret=access_key_secret, region_id=region_id
+    # )
+    # 2. 请求参数配置
+    request = build_create_instances_request(
+        image_id=image_id, vswitch_id=vswitch_id, security_group_id=security_group_id, zone_id=zone_id,
+        instance_type=instance_type, instance_name=instance_name, disk_size=disk_size, disk_category=disk_category,
+        key_pair_name=key_pair_name, tags=tags
+    )
+    request.set_Amount(amount)
+    # 3. 发送API请求,购买机器并启动
+    response = send_request(client=client, request=request)
+    if response.get('Code') is None:
+        instance_ids = response.get('InstanceIdSets').get('InstanceIdSet')
+        logging.info(f"success amount: {len(instance_ids)}, instance ids: {instance_ids}.")
+        # 获取机器运行状态
+        running_amount = 0
+        while running_amount < amount:
+            time.sleep(10)
+            running_amount, running_instances = check_instance_running(client=client, instance_ids=instance_ids)
+            logging.info(f"running amount: {running_amount}, running instances: {running_instances}.")
+        return instance_ids
+    else:
+        # 失败,记录报错信息,发送通知,停止并退出
+        logging.error(response)
+        sys.exit()
+
+
+def run_command(client, instance_ids, command):
+    """
+    批量执行命令
+    :param client: 客户端连接
+    :param instance_ids: 实例id列表, type-list, 最多能指定50台ECS实例ID
+    :param command: 命令 type-string
+    :return:
+    """
+    for i in range(len(instance_ids) // 50 + 1):
+        instance_id_list = instance_ids[i * 50:(i + 1) * 50]
+        if len(instance_id_list) == 0:
+            return
+        request = RunCommandRequest()
+        request.set_accept_format('json')
+        request.set_Type("RunShellScript")
+        request.set_CommandContent(command)
+        request.set_InstanceIds(instance_id_list)
+        response = send_request(client=client, request=request)
+        logging.info(response)
+
+# def run_per_command(client, instance, command):
+#     """
+#     批量执行命令
+#     :param client: 客户端连接
+#     :param instance_ids: 实例id列表, type-list, 最多能指定50台ECS实例ID
+#     :param command: 命令 type-string
+#     :return:
+#     """
+#     #for i in range(len(instance_ids) // 50 + 1)
+#     request = RunCommandRequest()
+#     request.set_accept_format('json')
+#     request.set_Type("RunShellScript")
+#     request.set_CommandContent(command)
+#     request.set_InstanceIds([instance])
+#     response = send_req(client=client, request=request)
+#     logging.info(response)
+#     return response
+
+
+def get_instance_ids(client, clb_id):
+    """
+    获取clb下所有服务器instanceId
+    :param client: 客户端连接
+    :param clb_id: 负载均衡id type-string
+    :return: instance_ids type-list
+    """
+    request = DescribeLoadBalancerAttributeRequest()
+    request.set_accept_format('json')
+    request.set_LoadBalancerId(clb_id)
+    response = send_request(client=client, request=request)
+    instance_ids = [instance["ServerId"] for instance in response["BackendServers"]["BackendServer"]]
+    return instance_ids
+
+
+def get_ip_address(client, instance_id):
+    """
+    获取实例IP地址
+    :param client: 客户端连接
+    :param instance_id: 实例id, type-string
+    :return: ip_address, type-string
+    """
+    request = DescribeNetworkInterfacesRequest()
+    request.set_accept_format('json')
+    request.set_InstanceId(instance_id)
+    response = send_request(client=client, request=request)
+    ip_address = response['NetworkInterfaceSets']['NetworkInterfaceSet'][0]['PrivateIpAddress']
+    return ip_address
+
+
+def set_weight_for_instances(client, clb_id, instance_id_list, weight):
+    """
+    同时设置多台服务器的clb权重,权重一样
+    :param client: 客户端连接
+    :param clb_id: clb_id
+    :param instance_id_list: 服务器id list
+    :param weight: 权重值
+    :return: None
+    """
+    for i in range(len(instance_id_list) // 20 + 1):
+        instances_list = instance_id_list[i * 20:(i + 1) * 20]
+        if len(instances_list) == 0:
+            return
+        BackendServers = [{"ServerId": instance_id, "Weight": weight} for instance_id in instances_list]
+        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', clb_id)
+        response = send_request(client=client, request=request)
+
+
+def send_file_to_ecs(client, instance_id_list, target_dir, name, content):
+    """
+    发送文件到ecs
+    :param client:
+    :param instance_id_list: 最多能指定50台ECS实例ID
+    :param target_dir: 文件存放目录 type-string
+    :param name: 文件名 type-string
+    :param content: 文件内容 type-string
+    :return:
+    """
+    for i in range(len(instance_id_list) // 50 + 1):
+        instance_ids = instance_id_list[i * 50:(i + 1) * 50]
+        if len(instance_ids) == 0:
+            return
+        request = SendFileRequest()
+        request.set_Content(content)
+        request.set_TargetDir(target_dir)
+        request.set_Name(name)
+        request.set_Overwrite(True)
+        request.set_InstanceIds(instance_ids)
+        response = send_request(client=client, request=request)
+
+
+def stop_instances(client, instance_ids, force_stop=False):
+    """
+    停止实例
+    :param client:
+    :param instance_ids: 实例ID, type-list
+    :param force_stop: 是否强制关机, True-强制关机, False-正常关机, type-bool
+    :return:
+    """
+    request = StopInstancesRequest()
+    request.set_InstanceIds(instance_ids)
+    request.set_ForceStop(force_stop)
+    response = send_request(client=client, request=request)
+    return response
+
+
+def release_instances(client, instance_ids, force=False):
+    """
+    释放实例
+    :param client:
+    :param instance_ids: instance_id, type-list
+    :param force: 是否强制释放, True-强制释放, False-正常释放, type-bool
+    :return:
+    """
+    request = DeleteInstancesRequest()
+    request.set_InstanceIds(instance_ids)
+    request.set_Force(force)
+    response = send_request(client=client, request=request)
+    return response
+
+
+def get_instances_status(client, instance_ids):
+    """
+    获取实例运行状态
+    :param client:
+    :param instance_ids: instance_id, type-liist
+    :return:
+    """
+    request = DescribeInstanceStatusRequest()
+    request.set_InstanceIds(instance_ids)
+    request.set_PageSize(50)
+    response = send_request(client=client, request=request)
+    return response
+
+
+def set_instance_weight_process(client, clb_id, instance_id_list, weight_list):
+    """
+    修改服务器的权重值
+    :param client: clb客户端连接
+    :param clb_id: clb id
+    :param instance_id_list: instance id list
+    :param weight_list: 权重修改列表 type-list [(weight, sleep_time), ...]
+    :return:
+    """
+    for weight, sleep_time in weight_list:
+        logging.info(f"weight = {weight}")
+        flag = True
+        while flag:
+            try:
+                set_weight_for_instances(client=client, clb_id=clb_id, instance_id_list=instance_id_list, weight=weight)
+                time.sleep(sleep_time)
+                flag = False
+            except Exception as e:
+                time.sleep(10)
+                continue
+
+
+def add_backend_servers(client, clb_id, instances):
+    """
+    服务器挂载到负载均衡(必须是状态为运行中的后端服务器才可以加入负载均衡实例,每次调用最多可添加20个后端服务器)
+    :param client:
+    :param clb_id:
+    :param instances: 实例列表 [(instance_id, ip), ...]
+    :return:
+    """
+    try:
+        for i in range(len(instances) // 20 + 1):
+            instances_list = instances[i * 20:(i + 1) * 20]
+            if len(instances_list) == 0:
+                return
+            request = AddBackendServersRequest()
+            request.set_accept_format('json')
+            request.set_LoadBalancerId(clb_id)
+            backend_servers = [
+                {"ServerId": instance_id, "Weight": "0", "Type": "ecs", "ServerIp": ip_address}
+                for instance_id, ip_address in instances_list]
+            request.set_BackendServers(backend_servers)
+            response = client.do_action_with_exception(request)
+            return response
+    except Exception as e:
+        logging.error(e)
+        sys.exit()
+
+
+def remove_backend_servers(client, clb_id, instances):
+    """
+    服务器从负载均衡移除(一次调用最多可以移除20个后端服务器)
+    :param client:
+    :param clb_id:
+    :param instances: 实例列表 [instance_id, ...]
+    :return:
+    """
+    try:
+        for i in range(len(instances) // 20 + 1):
+            instances_list = instances[i * 20:(i + 1) * 20]
+            if len(instances_list) == 0:
+                return
+            request = RemoveBackendServersRequest()
+            request.set_accept_format('json')
+            request.set_LoadBalancerId(clb_id)
+            backend_servers = [
+                {"ServerId": instance_id, "Weight": "0", "Type": "ecs"}
+                for instance_id in instances_list]
+            request.set_BackendServers(backend_servers)
+            response = client.do_action_with_exception(request)
+            return response
+    except Exception as e:
+        logging.error(e)
+        sys.exit()
+
+
+def set_instance_weight_process_with_clbs(client, clb_id_list, instance_id_list, weight_list):
+    """
+    修改服务器的权重值
+    :param client: clb客户端连接
+    :param clb_id_list: clb id list
+    :param instance_id_list: instance id list
+    :param weight_list: 权重修改列表 type-list [(weight, sleep_time), ...]
+    :return:
+    """
+    for weight, sleep_time in weight_list:
+        logging.info(f"修改权重中: weight = {weight}")
+        for clb_id in clb_id_list:
+            flag = True
+            while flag:
+                try:
+                    set_weight_for_instances(client=client, clb_id=clb_id, instance_id_list=instance_id_list, weight=weight)
+                    logging.info(f"clb: {clb_id} finished!")
+                    flag = False
+                except Exception as e:
+                    time.sleep(10)
+                    continue
+        time.sleep(sleep_time)
+
+
+def add_backend_servers_with_clbs(client, clb_id_list, instances):
+    """
+    服务器挂载到负载均衡(必须是状态为运行中的后端服务器才可以加入负载均衡实例,每次调用最多可添加20个后端服务器)
+    :param client:
+    :param clb_id_list:
+    :param instances: 实例列表 [(instance_id, ip), ...]
+    :return:
+    """
+    try:
+        for i in range(len(instances)//20 + 1):
+            instances_list = instances[i*20:(i+1)*20]
+            if len(instances_list) == 0:
+                return
+            for clb_id in clb_id_list:
+                request = AddBackendServersRequest()
+                request.set_accept_format('json')
+                request.set_LoadBalancerId(clb_id)
+                backend_servers = [
+                    {"ServerId": instance_id, "Weight": "0", "Type": "ecs", "ServerIp": ip_address}
+                    for instance_id, ip_address in instances_list]
+                request.set_BackendServers(backend_servers)
+                response = client.do_action_with_exception(request)
+                logging.info(f"clb: {clb_id} add backend servers finished!")
+            logging.info(f"i: {i}, count: {len(instances_list)}, instances: {instances_list} "
+                         f"add backend servers finished!")
+    except Exception as e:
+        logging.error(e)
+        sys.exit()
+
+
+def remove_backend_servers_with_clbs(client, clb_id_list, instances):
+    """
+    服务器从负载均衡移除(一次调用最多可以移除20个后端服务器)
+    :param client:
+    :param clb_id_list:
+    :param instances: 实例列表 [instance_id, ...]
+    :return:
+    """
+    try:
+        for i in range(len(instances)//20 + 1):
+            instances_list = instances[i*20:(i+1)*20]
+            if len(instances_list) == 0:
+                return
+            for clb_id in clb_id_list:
+                request = RemoveBackendServersRequest()
+                request.set_accept_format('json')
+                request.set_LoadBalancerId(clb_id)
+                backend_servers = [
+                    {"ServerId": instance_id, "Weight": "0", "Type": "ecs"}
+                    for instance_id in instances_list]
+                request.set_BackendServers(backend_servers)
+                response = client.do_action_with_exception(request)
+                logging.info(f"clb: {clb_id} remove backend servers finished!")
+            logging.info(f"i: {i}, count: {len(instances_list)}, instances: {instances_list} "
+                         f"remove backend servers finished!")
+    except Exception as e:
+        logging.error(e)
+        sys.exit()

+ 82 - 0
commonapi/commonapi_config.py

@@ -0,0 +1,82 @@
+import os
+import logging
+import sys
+
+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')
+
+
+# alb后端服务器_调试使用组
+# server_group_id_list = ["sgp-ec4gopoclruofsfmxu"]
+
+# clb 测试环境_临时调试使用
+# clb_id_list = ["lb-bp1i49h7ncw2c9nl3kp6u"]
+
+# commonapi clb 生产环境
+clb_id_list = ["lb-bp1xmaogphakz0l1o13mu"]
+
+# 后端服务器使用的端口
+port = "8182"
+
+# 修改负载均衡权限
+clb_client_params = {
+    'access_key_id': 'LTAIuPbTPL3LDDKN',
+    'access_key_secret': 'ORcNedKwWuwVtcq4IRFtUDZgS0b1le',
+    'region_id': 'cn-hangzhou'
+}
+
+alb_client_params = {
+    'access_key_id': 'LTAI5tASD5yEZLeC8ffmNebY',
+    'access_key_secret': '1PtsFRdp8viJmI78lEhNZR8MezWZBq',
+    'endpoint': 'alb.cn-hangzhou.aliyuncs.com',
+    'region_id': 'cn-hangzhou'
+}
+# 购买机器权限
+ecs_client_params = {
+    'access_key_id': 'LTAI4GBWbFvvXoXsSVBe1o9f',
+    'access_key_secret': 'kRAikWitb4kDxaAyBqNrmLmllMEDO3',
+    'region_id': 'cn-hangzhou'
+}
+
+docker_config = {
+    'username': 'stuuudys',
+    'password': 'Qingqu@2019',
+    'registry': 'registry-vpc.cn-hangzhou.aliyuncs.com'
+}
+
+# 机器配置
+instance_config_h = {
+    # 使用的镜像信息
+    'image_id': 'm-bp15xqcuacm4zw2h2gi6',
+    # 设置实例规格
+    'instance_type': 'ecs.c6.xlarge',
+    # 选择的交换机
+    'vswitch_id': 'vsw-bp19lpjwtc6j0p0m9mdc2',
+    # 当前VPC类型的安全组
+    'security_group_id': 'sg-bp1irhrkr4vfj272hk4y',
+    # 硬盘的大小,单位:G
+    'disk_size': '200',
+    # 服务器命名
+    'instance_name': 'commonapi-[1,2]',
+    # 服务器所在区域
+    'zone_id': 'cn-hangzhou-h',
+    # 磁盘类型:云盘
+    'disk_category': 'cloud_efficiency',
+    # 密钥
+    'key_pair_name': 'stuuudy',
+    # tag
+    'tags': [{"Key": "ecs", "Value": "commonapi.prod"}]
+}
+
+
+# 服务启动脚本
+start_sh_dir = os.path.dirname(os.path.realpath(__file__))
+start_sh_filename = 'commonapi_start.sh'
+with open(file=os.path.join(start_sh_dir, start_sh_filename), mode='r', encoding='utf-8') as rf:
+    file_content = rf.read()
+start_sh = {
+    'target_dir': '/home/commonapi_server_sh',
+    'name': start_sh_filename,
+    'content': file_content,
+}

+ 100 - 0
commonapi/commonapi_reduce_with_count.py

@@ -0,0 +1,100 @@
+import sys
+import time
+import clb_utils
+import commonapi_config
+import logging
+
+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')
+
+
+def remove_instances(ecs_client, clb_client, instance_ids):
+    """
+    停止并释放机器
+    :param ecs_client:
+    :param clb_client:
+    :param instance_ids: instanceId type-list
+    :return: None
+    """
+    # 1. 摘流量
+    clb_utils.set_instance_weight_process_with_clbs(client=clb_client,
+                                                clb_id_list=commonapi_config.clb_id_list,
+                                                instance_id_list=instance_ids,
+                                                weight_list=[(0, 20)])
+    logging.info(f"set weight = 0 finished, instances: {instance_ids}")
+    time.sleep(10)
+    # 2.移除clb
+    clb_utils.remove_backend_servers_with_clbs(client=clb_client,
+                                           clb_id_list=commonapi_config.clb_id_list,
+                                           instances=instance_ids)
+    # 3. 停止机器
+    clb_utils.stop_instances(client=ecs_client, instance_ids=instance_ids)
+    logging.info(f"instances stop finished, instances: {instance_ids}")
+    # 4. 判断机器运行状态是否为Stopped
+    while True:
+        response = clb_utils.get_instances_status(client=ecs_client, instance_ids=instance_ids)
+        if response.get('Code') is None:
+            instances_list = response.get('InstanceStatuses').get('InstanceStatus')
+            # logging.info(instances_list)
+            stopped_instances = [instance.get('InstanceId') for instance in instances_list
+                                 if instance.get('Status') == 'Stopped']
+            if len(stopped_instances) == len(instance_ids):
+                logging.info(f"instances stopped status set success, instances: {stopped_instances}")
+                break
+            else:
+                logging.info(f"stopped instances count = {len(stopped_instances)}, instances: {stopped_instances}")
+                time.sleep(5)
+        else:
+            logging.error(response)
+            sys.exit()
+    # 5. 释放机器
+    response = clb_utils.release_instances(client=ecs_client, instance_ids=stopped_instances)
+    if response.get('Code') is None:
+        logging.info(f"release instances finished, instances: {stopped_instances}")
+    else:
+        logging.error(f"release instances fail!!!")
+        sys.exit()
+
+
+def main():
+    try:
+        clb_client = clb_utils.connect_client(
+            access_key_id=commonapi_config.clb_client_params['access_key_id'],
+            access_key_secret=commonapi_config.clb_client_params['access_key_secret'],
+            region_id=commonapi_config.clb_client_params['region_id']
+        )
+        ecs_client = clb_utils.connect_client(
+            access_key_id=commonapi_config.ecs_client_params['access_key_id'],
+            access_key_secret=commonapi_config.ecs_client_params['access_key_secret'],
+            region_id=commonapi_config.ecs_client_params['region_id']
+        )
+
+        # 获取指定释放的机器数量
+        reduce_count = int(sys.argv[1])
+        logging.info(f"reduce instances count: {reduce_count}")
+
+        # 获取clb下所有机器
+        online_instance_ids = clb_utils.get_instance_ids(client=clb_client, clb_id=commonapi_config.clb_id_list[0])
+        online_instance_count = len(online_instance_ids)
+        logging.info(f"online instance count: {online_instance_count}.")
+        logging.info(f"online instance ids: {online_instance_ids}")
+
+        # if online_instance_count - reduce_count < 4:
+        #     logging.error("缩容后服务器数量不能小于4台")
+        #     sys.exit()
+
+        # 获取前count台机器进行释放
+        reduce_instance_ids = online_instance_ids[:reduce_count]
+        logging.info(f"reduce instances: {reduce_instance_ids}")
+
+        # 停止并释放机器
+        remove_instances(ecs_client=ecs_client, clb_client=clb_client, instance_ids=reduce_instance_ids)
+        logging.info(f"stop & release instances end!")
+    except Exception as e:
+        logging.error(e)
+        sys.exit()
+
+
+if __name__ == '__main__':
+    main()

+ 132 - 0
commonapi/commonapi_scaling_h_count.py

@@ -0,0 +1,132 @@
+import sys
+import os
+import asyncio
+import logging
+import time
+import requests
+
+import clb_utils
+import commonapi_config
+
+from concurrent.futures import ThreadPoolExecutor
+
+
+health_instances = []
+
+
+def commonapi_health_check(client, instance_id, max_wait_time=None):
+    """
+    服务健康检查
+    :param client: 客户端连接
+    :param instance_id: instanceId
+    :param max_wait_time: 最长等待时间,单位:s
+    :return:
+    """
+    global health_instances
+    start_time = time.time()
+    ip_address = clb_utils.get_ip_address(client=client, instance_id=instance_id)
+    while True:
+        health_check_url = f"http://{ip_address}:8182/commonapi/test"
+        try:
+            http_code = requests.get(health_check_url).status_code
+        except:
+            logging.info(f"images is downloading ip: {ip_address}")
+            http_code = 0
+
+        if http_code == 200:
+            health_instances.append((instance_id, ip_address))
+            logging.info(f"health check success, instance: {instance_id}/{ip_address}")
+            break
+        elif max_wait_time is not None:
+            now = time.time()
+            if (now - start_time) >= max_wait_time:
+                logging.info(f"health check error, instance: {instance_id}/{ip_address}")
+                break
+            else:
+                time.sleep(10)
+        else:
+            time.sleep(10)
+
+
+async def ess_instance(ecs_client, clb_client, ess_count, max_workers):
+    """
+    扩容机器并运行新服务
+    :param ecs_client: 购买机器客户端连接
+    :param clb_client: 修改负载均衡权限
+    :param ess_count: 扩容数量
+    :param max_workers: 线程数
+    :return:
+    """
+    # 1. 购买机器并启动
+    ess_instance_ids = clb_utils.create_multiple_instances(
+        amount=ess_count,
+        client=ecs_client,
+        **commonapi_config.instance_config_h,
+    )
+    time.sleep(60)
+
+    # 2. 发送启动脚本到机器上
+    clb_utils.send_file_to_ecs(client=ecs_client, instance_id_list=ess_instance_ids, **commonapi_config.start_sh)
+    logging.info(f"send start shell file finished, instances: {ess_instance_ids}")
+    # 3. 启动服务
+    start_sh_param = "latest"
+    server_start_sh = os.path.join(commonapi_config.start_sh['target_dir'], commonapi_config.start_sh['name'])
+    server_start_commend = f"sh {server_start_sh} {start_sh_param}"
+    clb_utils.run_command(client=ecs_client, instance_ids=ess_instance_ids, command=server_start_commend)
+    # 4. 异步探活
+    global health_instances
+    health_instances = []
+    max_wait_time = 180
+    loop = asyncio.get_running_loop()
+    executor = ThreadPoolExecutor(max_workers=max_workers)
+    tasks = [
+        loop.run_in_executor(executor, commonapi_health_check, *args) for args in
+        [(clb_client, instance_id, max_wait_time) for instance_id in ess_instance_ids]
+    ]
+    await asyncio.wait(tasks)
+    logging.info(f"health instances count: {len(health_instances)}, {health_instances}")
+    # 5. 挂载流量
+    if len(health_instances) > 0:
+        # 所有机器探活成功
+        time.sleep(20)
+        clb_utils.add_backend_servers_with_clbs(client=clb_client,
+                                            clb_id_list=commonapi_config.clb_id_list,
+                                            instances=health_instances)
+        add_weight_list = [(10, 5), (20, 5), (40, 5), (60, 5), (80, 5), (100, 5)]
+        health_instance_ids = [instance_id for instance_id, _ in health_instances]
+        clb_utils.set_instance_weight_process_with_clbs(client=clb_client,
+                                                    clb_id_list=commonapi_config.clb_id_list,
+                                                    instance_id_list=health_instance_ids,
+                                                    weight_list=add_weight_list)
+        logging.info(f"ess count: {ess_count}, "
+                     f"create count: {len(ess_instance_ids)}, "
+                     f"finished count: {len(health_instance_ids)}")
+    else:
+        logging.info(f"ess count: {ess_count}, "
+                     f"create count: {len(ess_instance_ids)}, "
+                     f"health count: {len(health_instances)}")
+        sys.exit()
+
+
+def main():
+    try:
+        clb_client = clb_utils.connect_client(access_key_id=commonapi_config.clb_client_params['access_key_id'],
+                                          access_key_secret=commonapi_config.clb_client_params['access_key_secret'],
+                                          region_id=commonapi_config.clb_client_params['region_id'])
+        ecs_client = clb_utils.connect_client(access_key_id=commonapi_config.ecs_client_params['access_key_id'],
+                                             access_key_secret=commonapi_config.ecs_client_params['access_key_secret'],
+                                             region_id=commonapi_config.ecs_client_params['region_id'])
+        # 获取批量创建ECS实例的数量
+        ess_instance_count = int(sys.argv[1])
+        # 扩容机器并启动服务
+        logging.info(f"ess instances start ...")
+        logging.info(f"ess instance count: {ess_instance_count}")
+        asyncio.run(ess_instance(ecs_client=ecs_client, clb_client=clb_client,
+                                 ess_count=ess_instance_count, max_workers=2))
+        logging.info(f"ess instances end!")
+    except Exception as e:
+        logging.error(e)
+
+
+if __name__ == '__main__':
+    main()

+ 3 - 0
commonapi/commonapi_start.sh

@@ -0,0 +1,3 @@
+#/bin/bash
+docker login --username=stuuudys --password=Qingqu@2019   registry-vpc.cn-hangzhou.aliyuncs.com
+docker run --cap-add=SYS_PTRACE  -d -it --name commonapi  -v  /datalog:/datalog  --restart=always --network host    registry-vpc.cn-hangzhou.aliyuncs.com/stuuudy/commonapi:$1

+ 22 - 0
commonapi/commonapi_unittest.py

@@ -0,0 +1,22 @@
+import unittest
+import clb_utils
+import commonapi_config
+import logging
+
+class MyTestCase(unittest.TestCase):
+
+    def test_create_multiple_instances(self):
+        ecs_client = clb_utils.connect_client(access_key_id=commonapi_config.ecs_client_params['access_key_id'],
+                                              access_key_secret=commonapi_config.ecs_client_params['access_key_secret'],
+                                              region_id=commonapi_config.ecs_client_params['region_id'])
+
+        ess_instance_ids = clb_utils.create_multiple_instances(
+            amount=1,
+            client=ecs_client,
+            **commonapi_config.instance_config_h,
+        )
+        logging.info(ess_instance_ids)
+
+
+if __name__ == '__main__':
+    unittest.main()

+ 1 - 1
gateway/alb_gateway_unittest.py

@@ -96,7 +96,7 @@ class MyTestCase(unittest.TestCase):
                                           region_id=gateway_config.ecs_client_params['region_id'])
         instance_id = 'i-bp1933o7phjzrwg1x3kd'
         container_name_list = ['piaoquan-gateway', 'gateway']
-        alb_gateway_update_cluster.remove_container_image(ecs_client, instance_id, container_name_list)
+        alb_gateway_update_list.remove_container_image(ecs_client, instance_id, container_name_list)
 
 
 

+ 1 - 1
gateway/clb_gateway_reduce_with_count.py

@@ -24,7 +24,7 @@ def remove_instances(ecs_client, clb_client, instance_ids):
                                                 weight_list=[(0, 20)])
     logging.info(f"set weight = 0 finished, instances: {instance_ids}")
     time.sleep(10)
-    # 2.移除slb
+    # 2.移除clb
     clb_utils.remove_backend_servers_with_clbs(client=clb_client,
                                            clb_id_list=gateway_config.clb_id_list,
                                            instances=instance_ids)

+ 2 - 2
gateway/clb_gateway_update_list.py

@@ -158,7 +158,7 @@ async def update_instance(ecs_client, clb_client, instance_ids, max_workers, ver
     """
     线上机器更新
     :param ecs_client:
-    :param clb_client: slb客户端连接
+    :param clb_client: clb客户端连接
     :param instance_ids: instanceId type-list
     :param max_workers:
     :param version: 版本标记
@@ -246,7 +246,7 @@ def remove_instances(ecs_client, clb_client, instance_ids):
                                                 weight_list=[(0, 20)])
     logging.info(f"set weight = 0 finished, instances: {instance_ids}")
     time.sleep(10)
-    # 2.移除slb
+    # 2.移除clb
     clb_utils.remove_backend_servers_with_clbs(client=clb_client,
                                            clb_id_list=gateway_config.clb_id_list,
                                            instances=instance_ids)

+ 13 - 13
gateway/clb_utils.py

@@ -244,7 +244,7 @@ def run_command(client, instance_ids, command):
 
 def get_instance_ids(client, clb_id):
     """
-    获取slb下所有服务器instanceId
+    获取clb下所有服务器instanceId
     :param client: 客户端连接
     :param clb_id: 负载均衡id type-string
     :return: instance_ids type-list
@@ -274,7 +274,7 @@ def get_ip_address(client, instance_id):
 
 def set_weight_for_instances(client, clb_id, instance_id_list, weight):
     """
-    同时设置多台服务器的slb权重,权重一样
+    同时设置多台服务器的clb权重,权重一样
     :param client: 客户端连接
     :param clb_id: clb_id
     :param instance_id_list: 服务器id list
@@ -386,11 +386,11 @@ def set_instance_weight_process(client, clb_id, instance_id_list, weight_list):
                 continue
 
 
-def add_backend_servers(client, slb_id, instances):
+def add_backend_servers(client, clb_id, instances):
     """
     服务器挂载到负载均衡(必须是状态为运行中的后端服务器才可以加入负载均衡实例,每次调用最多可添加20个后端服务器)
     :param client:
-    :param slb_id:
+    :param clb_id:
     :param instances: 实例列表 [(instance_id, ip), ...]
     :return:
     """
@@ -401,7 +401,7 @@ def add_backend_servers(client, slb_id, instances):
                 return
             request = AddBackendServersRequest()
             request.set_accept_format('json')
-            request.set_LoadBalancerId(slb_id)
+            request.set_LoadBalancerId(clb_id)
             backend_servers = [
                 {"ServerId": instance_id, "Weight": "0", "Type": "ecs", "ServerIp": ip_address}
                 for instance_id, ip_address in instances_list]
@@ -413,11 +413,11 @@ def add_backend_servers(client, slb_id, instances):
         sys.exit()
 
 
-def remove_backend_servers(client, slb_id, instances):
+def remove_backend_servers(client, clb_id, instances):
     """
     服务器从负载均衡移除(一次调用最多可以移除20个后端服务器)
     :param client:
-    :param slb_id:
+    :param clb_id:
     :param instances: 实例列表 [instance_id, ...]
     :return:
     """
@@ -428,7 +428,7 @@ def remove_backend_servers(client, slb_id, instances):
                 return
             request = RemoveBackendServersRequest()
             request.set_accept_format('json')
-            request.set_LoadBalancerId(slb_id)
+            request.set_LoadBalancerId(clb_id)
             backend_servers = [
                 {"ServerId": instance_id, "Weight": "0", "Type": "ecs"}
                 for instance_id in instances_list]
@@ -456,7 +456,7 @@ def set_instance_weight_process_with_clbs(client, clb_id_list, instance_id_list,
             while flag:
                 try:
                     set_weight_for_instances(client=client, clb_id=clb_id, instance_id_list=instance_id_list, weight=weight)
-                    logging.info(f"slb: {clb_id} finished!")
+                    logging.info(f"clb: {clb_id} finished!")
                     flag = False
                 except Exception as e:
                     time.sleep(10)
@@ -486,7 +486,7 @@ def add_backend_servers_with_clbs(client, clb_id_list, instances):
                     for instance_id, ip_address in instances_list]
                 request.set_BackendServers(backend_servers)
                 response = client.do_action_with_exception(request)
-                logging.info(f"slb: {clb_id} add backend servers finished!")
+                logging.info(f"clb: {clb_id} add backend servers finished!")
             logging.info(f"i: {i}, count: {len(instances_list)}, instances: {instances_list} "
                          f"add backend servers finished!")
     except Exception as e:
@@ -507,16 +507,16 @@ def remove_backend_servers_with_clbs(client, clb_id_list, instances):
             instances_list = instances[i*20:(i+1)*20]
             if len(instances_list) == 0:
                 return
-            for slb_id in clb_id_list:
+            for clb_id in clb_id_list:
                 request = RemoveBackendServersRequest()
                 request.set_accept_format('json')
-                request.set_LoadBalancerId(slb_id)
+                request.set_LoadBalancerId(clb_id)
                 backend_servers = [
                     {"ServerId": instance_id, "Weight": "0", "Type": "ecs"}
                     for instance_id in instances_list]
                 request.set_BackendServers(backend_servers)
                 response = client.do_action_with_exception(request)
-                logging.info(f"slb: {slb_id} remove backend servers finished!")
+                logging.info(f"clb: {clb_id} remove backend servers finished!")
             logging.info(f"i: {i}, count: {len(instances_list)}, instances: {instances_list} "
                          f"remove backend servers finished!")
     except Exception as e:

+ 2 - 2
gateway/gateway_config.py

@@ -106,8 +106,8 @@ instance_config_j_clb = {
 # 服务启动脚本
 start_sh_dir = os.path.dirname(os.path.realpath(__file__))
 start_sh_filename = 'gateway_start.sh'
-with open(file=os.path.join(start_sh_dir, start_sh_filename), mode='w', encoding='utf-8') as wf:
-    file_content = wf.read()
+with open(file=os.path.join(start_sh_dir, start_sh_filename), mode='r', encoding='utf-8') as rf:
+    file_content = rf.read()
     # logging.info(f"start sh file content: {file_content}")
 start_sh = {
     'target_dir': '/home/gateway_server_sh',

+ 2 - 5
longvideoapi/longvideoapi_config.py

@@ -5,14 +5,11 @@ 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')
 
-# longvideoapi-alb-ecs组-生产环境
-server_group_id_list = ["sgp-h79h3lkvua1xs3418y"]
-
 # alb后端服务器_调试使用组
 # server_group_id_list = ["sgp-ec4gopoclruofsfmxu"]
 
-
-
+# longvideoapi-alb-ecs组-生产环境
+server_group_id_list = ["sgp-h79h3lkvua1xs3418y"]
 
 # 后端服务器使用的端口
 port = "8080"