专栏首页python3Python 协程检测Kubernetes服务端口

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 + "\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秒钟就完成了,使用协程非常的高效!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • python过滤 Kubernetes api数据

    其中 pod_name 对应 items-->subsets-->addresses-->targetRef-->name

    py3study
  • 运维python进行(一) nmap扫描

    最近为了加强服务器安全性和监管,需要每天把公司服务器开放端口扫描记录,一旦出现增加减少能发现。

    py3study
  • 【python学习】新手基础程序练习(二

    py3study
  • 深入理解Java内部类

         内部类就是定义在一个类中的另外一个类,是一种从属关系。在没有实际了解内部类之前,我始终困惑,为什么要在一个类中定义另外一个类,这不是增加代码结构复杂度...

    Single
  • ASP.NET Core中的ActionFilter与DI

      前几篇文章都是讲ASP.NET Core MVC中的依赖注入(DI)与扩展点的,也许大家都发现在ASP.NET CORE中所有的组件都是通过依赖注入来扩展的...

    yoyofx
  • 检测ip和port是否可连接的方法

    如果不可连接,会提示连接失败,否则如果cmd出现一大段空白和不可操作界面则表示连接成功。

    砸漏
  • 快速学习-使用 spring 的 IOC 解决程序耦合

    本章我们使用的案例是,账户的业务层和持久层的依赖关系解决。在开始 spring 的配置之前,我们要先准备一下环境。由于我们是使用 spring 解决依赖关系,并...

    cwl_java
  • [PYTHON] 核心编程笔记之七-Py

    字典是Python语言中唯一的映射类型,映射类型对象里哈希值(键)和指向的对象(值)是一对多的关系,字典对象可变,它是一个容器类型,能存储任意个Python对象

    py3study
  • 华为网络工程师 | 四个小技能:双向转发检查BFD、ospf 调用bfd 加快收敛、端口安全、端口镜像

    BFD:Bidirectional Forwarding Detection,双向转发检查

    网络技术联盟站
  • Python基础---类的内置方法

    __init__(): __init__方法在类的一个对象被建立时,马上运行。这个方法可以用来对你的对象做一些你希望的初始化。注意,这个名称的开始和结尾都是双下...

    我被狗咬了

扫码关注云+社区

领取腾讯云代金券