zoukankan      html  css  js  c++  java
  • Python 协程检测Kubernetes服务端口

    一、需求分析

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

    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 + "
    "
                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))
    View Code

    执行输出:

    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
    View Code

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

  • 相关阅读:
    训练总结
    图论--最短路--SPFA模板(能过题,真没错的模板)
    图论--最短路-- Dijkstra模板(目前见到的最好用的)
    The 2019 Asia Nanchang First Round Online Programming Contest B Fire-Fighting Hero(阅读理解)
    关于RMQ问题的四种解法
    The Preliminary Contest for ICPC Asia Xuzhou 2019 徐州网络赛 K题 center
    The Preliminary Contest for ICPC Asia Xuzhou 2019 徐州网络赛 XKC's basketball team
    The Preliminary Contest for ICPC Asia Xuzhou 2019 徐州网络赛 D Carneginon
    ZOJ 3607 Lazier Salesgirl (枚举)
    ZOJ 3605 Find the Marble(dp)
  • 原文地址:https://www.cnblogs.com/xiao987334176/p/10235019.html
Copyright © 2011-2022 走看看