Python 协程检测Kubernetes服务端口

发布时间:2020-02-18 09:49:15编辑:admin阅读(2285)

    一、需求分析

    在上一篇文章,链接如下:

    https://www.cnblogs.com/xiao987334176/p/10237551.html

     

    已经得到了需要的数据,现在需要对这些端口做检测,判断端口是否正常!

    实际情况是,有上百个端口需要检测。如果一个个检测,可能需要花费几分钟的时间,效率不够快!

    那么首先想到的就是多进程,但是一个进程会消耗一个CPU。

    在不影响性能的情况下,最快的办法,就是使用协程。它是异步的,遇到io会自动切换!

     

    二、协程

    介绍

     协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。

     

    关于 进程、线程和协程的理解,请参考链接:

    https://www.cnblogs.com/guolei2570/p/8810536.html

     

    这篇文章,有大量的图片解释,通俗易懂!

     

    安装

    使用协程,需要安装模块

    pip3 install gevent

    什么是猴子补丁(monkey patch)

    monkey patch指的是在执行时动态替换,通常是在startup的时候.
    用过gevent就会知道,会在最开头的地方gevent.monkey.patch_all();把标准库中的thread/socket等给替换掉.这样我们在后面使用socket的时候能够跟寻常一样使用,无需改动不论什么代码,可是它变成非堵塞的了.

     

    使用

    导入模块时,必须要导入猴子补丁

    from gevent import monkey; monkey.patch_all()
    import gevent

    示例

    from gevent import monkey;monkey.patch_all()
    # 它会把下面导入的所有的模块中的IO操作都打成一个包,gevent就能够认识这些IO了
    import time
    import gevent
    
    
    def eat():
        print('eating1')
        time.sleep(1)  # 延时调用
        print(time.time(),'eating2')
    
    
    def play():
        print('playing1')
        time.sleep(1)  # 延时调用
        print(time.time(),'playing2')
    
    
    g1 = gevent.spawn(eat)  # 创建一个协程对象g1
    g2 = gevent.spawn(play)
    g1.join()  # 等待g1结束
    g2.join()

     

    执行输出:

    eating1
    playing1
    1546917759.6040378 eating2
    1546917759.6040378 playing2

    看时间戳,可以发现,即使睡眠了1秒,2个函数几乎是同时运行的

     

    三、正式代码

    #!/usr/bin/env python
    # coding: utf-8
    import os
    import json
    import time
    import socket
    from gevent import monkey;monkey.patch_all()
    import gevent
    
    # data = ""
    # with open('test.json') as f:
    #     data = json.loads(f.read())
    
    # api整理好的json数据
    data = {"voucher-center-master": [
        {"server_port": 8012, "ip": "192.169.167.105", "pod_name": "voucher-center-rc-p20kk", "nodeName": "job-node149",
         "beejob_port": 3011},
        {"server_port": 8012, "ip": "192.169.183.26", "pod_name": "voucher-center-rc-vknkt", "nodeName": "job-node137",
         "beejob_port": 3011},
        {"server_port": 8012, "ip": "192.169.242.29", "pod_name": "voucher-center-rc-0x482", "nodeName": "job-node145",
         "beejob_port": 3011},
        {"server_port": 8012, "ip": "192.169.76.159", "pod_name": "voucher-center-rc-xtxfb", "nodeName": "job-node151",
         "beejob_port": 3011},
        {"server_port": 8012, "ip": "192.169.98.159", "pod_name": "voucher-center-rc-n9wkl", "nodeName": "job-node147",
         "beejob_port": 3011}]}
    
    
    class CheckServer(object):  # 检查服务端口
        def __init__(self):
            self.process_list = []  # 进程列表
    
        def check_tcp(self, ip, port, timeout=1):
            """
            检测tcp端口
            :param ip: ip地址
            :param port: 端口号
            :param timeout: 超时时间
            :return: bool
            """
            flag = False
            try:
                socket.setdefaulttimeout(timeout)  # 整个socket层设置超时时间
                cs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                address = (str(ip), int(port))
                status = cs.connect_ex((address))  # 开始连接
                cs.settimeout(timeout)
    
                if not status:
                    flag = True
    
                return flag
            except Exception as e:
                print("error:%s" % e)
                return flag
    
        def write_log(self, content):
            """
            写入日志文件
            :param content: 写入内容
            :return:
            """
            path = "output.log"  # 日志文件
            with open(path, mode='a+', encoding='utf-8') as f:
                content = time.strftime('%Y-%m-%d %H:%M:%S') + ' ' + content + "\n"
                print(content)
                f.write(content)
    
        def run(self, name, ip, port, category):
            """
            运行程序
            :param name: 名称
            :param ip: ip
            :param port: 端口
            :param category: 类别
            :return:
            """
            self.write_log("name:{} {}_ip:{} 检查端口: {} 状态:{}".format(name, category, ip, port, self.check_tcp(ip, port)))
    
        def main(self):
            for i in data:  # 遍历字典
                # print("name",i)
                for j in data[i]:  # 遍历节点数据
                    if j.get('server_port'):  # 获取server_port
                        if j.get('ip'):
                            ip = j['ip']
                            port = j['server_port']
                            # 添加到进程列表中
                            self.process_list.append(gevent.spawn(self.run, i, ip, port, 'server'))
    
                    if j.get('beejob_port'):  # 获取beejob_port
                        if j.get('ip'):
                            ip = j['ip']
                            port = j['beejob_port']
                            # 添加到进程列表中
                            self.process_list.append(gevent.spawn(self.run, i, ip, port, 'beejob'))
    
            return self.process_list
    
    
    if __name__ == '__main__':
        startime = time.time()  # 开始时间
        process_list = CheckServer().main()
        gevent.joinall(process_list)  # 使用协程执行所有协程
    
        endtime = time.time()
        take_time = endtime - startime
    
        if take_time < 1:  # 判断不足1秒时
            take_time = 1  # 设置为1秒
        # 计算花费时间
        m, s = divmod(take_time, 60)
        h, m = divmod(m, 60)
    
        print("本次花费时间 %02d:%02d:%02d" % (h, m, s))

     

    执行输出:

    2019-01-08 11:27:54 name:voucher-center-master server_ip:192.169.167.105 检查端口: 8012 状态:False
    
    2019-01-08 11:27:54 name:voucher-center-master beejob_ip:192.169.167.105 检查端口: 3011 状态:False
    
    2019-01-08 11:27:54 name:voucher-center-master server_ip:192.169.183.26 检查端口: 8012 状态:False
    
    2019-01-08 11:27:54 name:voucher-center-master beejob_ip:192.169.183.26 检查端口: 3011 状态:False
    
    2019-01-08 11:27:54 name:voucher-center-master server_ip:192.169.242.29 检查端口: 8012 状态:False
    
    2019-01-08 11:27:54 name:voucher-center-master beejob_ip:192.169.242.29 检查端口: 3011 状态:False
    
    2019-01-08 11:27:54 name:voucher-center-master server_ip:192.169.76.159 检查端口: 8012 状态:False
    
    2019-01-08 11:27:54 name:voucher-center-master beejob_ip:192.169.76.159 检查端口: 3011 状态:False
    
    2019-01-08 11:27:54 name:voucher-center-master server_ip:192.169.98.159 检查端口: 8012 状态:False
    
    2019-01-08 11:27:54 name:voucher-center-master beejob_ip:192.169.98.159 检查端口: 3011 状态:False
    
    本次花费时间 00:00:01

     

    可以发现,即使有那么多端口,1秒钟就完成了,使用协程非常的高效!


关键字