python和websocket构建实时日志跟踪器的步骤

 更新时间:2021年04月12日 14:16:17   作者:鸡仔说  
这篇文章主要介绍了python和websocket构建实时日志跟踪器的步骤,帮助大家更好的理解和学习使用python,感兴趣的朋友可以了解下

前言

websocket 是一种网络传输协议。可在单个 TCP 连接上进行全双工通信。基于此,websocket 使得客户端与服务端的通信变得更加简便和高效。

什么是 websocket

websocket 是独立的、创建在 TCP 上的协议。该协议在 2008 年诞生,并在 2011 年成为国际标准。它的一个主要特点是——全双工,即一旦建立连接,服务端或客户端可以主动向对方推送消息。

在 websocket 出现之前,网站如果需要实现推送技术,都是采用轮询的方式,即浏览器每隔一段时间就向服务器发出请求。这种模式的缺点在于,浏览器需要不断向服务器发送请求,消耗很多的带宽资源。比较新的 Comet 技术虽然也可以实现双向通信,但依然需要反复发送请求,并且 Comet 中普遍采用的 HTTP 长连接也会消耗服务器资源。

基于以上的情况,HTML5 定义了 websocket 协议,能够更好的节省服务器和带宽资源。并且实现高效的实时通信。目前,所有的浏览器都支持它。

websocket 通信原理和机制

websocket 虽然是一种新的协议,但它不能够脱离 http 单独存在,当客户端构建一个 websocket 实例,并且向服务端连接时,会首先发起一个 http 报文请求。告诉服务端需要将通信协议切换至 websocket。

如果服务端支持 websocket 协议,那么它会将通信协议切换至 websocket 并且返回响应报文。此时的返回状态码是 101,表示同意协议转换请求,接下来便可以进行数据传输了。

websocket 之所以借助 HTTP 完成握手协议,是因为有良好的兼容性,默认端口是 80 和 443。握手阶段不容易被防火墙屏蔽。

websocket 的特点

  • 开销小,服务器和客户端交换数据时,协议包头部包含较少的信息
  • 实时性高,协议采用全双工,相对于 http 请求客户端发起请求,服务端才能响应的模式,延迟明显更低
  • 与 HTTP 有良好的兼容性,默认端口是 80 和 443。握手采用 HTTP 协议,不容易被防火墙屏蔽
  • 支持文本和二进制数据传输
  • 支持自定义拓展,用户可以自己实现自定义的子协议
  • 通过心跳机制保持服务端与客户端的长连接

构建实时日志跟踪的小例子

服务端开启一个监听日志脚本的服务,服务会限制允许访问的路径范围(防止黑客利用程序漏洞,扫描整个服务器);服务器通过解析客户端的请求,返回日志的消息内容给客户端;服务器定时发送心跳检测给客户端,如果没有收到客户端的响应,则断开连接

服务端核心程序代码逻辑如下

with open(file_path) as f:
      # 首次读取指定行数(NUM_LINES)的日志文件,发送给客户端
            content = ''.join(deque(f, NUM_LINES))
            content = conv.convert(content, full=False)
            await websocket.send(content)
      
      # 如果发现客户端有 tail 请求,则进行 tail 日志追踪
            if tail:
        # 首先创建发起这次请求的心跳时间
                last_heartbeat = time.time()
                while True:
          # 每次 tail 服务端最新的日志记录,返回给客户端
                    content = f.read()
                    if content:
                        content = conv.convert(content, full=False)
                        await websocket.send(content)
                    else:
                        await asyncio.sleep(1)

                    # 检测这次请求距上一次发起请求,是不是已经超过了最长心跳检测时长,如果是,发起心跳检测
                    if time.time() - last_heartbeat > HEARTBEAT_INTERVAL:
                        try:
                            await websocket.send('ping')
                            pong = await asyncio.wait_for(websocket.recv(), 5)
                            logger.info(f"pong:{pong}")
                            if pong != 'pong':
                                raise Exception()
                        except Exception:
                            raise Exception('Ping error')
                        else:
                            last_heartbeat = time.time()
            else:
                await websocket.close()

客户端就非常简单了,监听服务端日志的文件,发现有新的日志产生则输出日志或者直接将日志实时展示在前端页面上。相应地,如果需要长期监听,那么当服务端发送心跳检测的信号过来,也需要回应响应的心跳反馈

客户端核心代码逻辑如下

async def consumer_handler(websocket: WebSocketClientProtocol) -> None:
    async for message in websocket:
        log_message(message)
        if message == "ping":
            await websocket.send("pong")

async def cousume(hostname: str, port: int, log_file: str, tail:bool=True) -> None:
    websocket_resource_url = f"ws://{hostname}:{port}{log_file}"
    if tail:
        websocket_resource_url = f"{websocket_resource_url}?tail=1"
    async with websockets.connect(websocket_resource_url) as websocket:
        await consumer_handler(websocket)

def log_message(message: str) -> None:
    logger.info(f"Message: {message}")

这里模拟一个日志生产文件

代码逻辑如下

import os

from loguru import logger

class LoggerExtend(object):
    # 存放目录名称
    folder = '../logs'

    def __init__(self, filename, folder=None):

        self.folder = folder or self.folder

        if not os.path.exists(self.folder):
            os.mkdir(self.folder)

        self.file = self.folder + '/' + filename

        logger.add(self.file, rotation="100 MB")

    @property
    def get_logger(self):
        return logger

if __name__ == '__main__':
    logger = LoggerExtend(os.path.basename(__file__).replace(".py", ".log")).get_logger
    import time
    while True:

        logger.info("你好aaa")

最后依次启动日志生产程序→服务端程序→客户端程序

日志生产文件启动后,运行效果如下

服务端启动程序运行,无运行日志产生

这时候启动客户端程序,运行效果如下

完整代码请移步至 GitHub 查看

https://github.com/hacksman/l...

日志生产程序路径:

common/logger_extend.py

服务端程序路径:

websoctet_lab/log_server.py

客户端程序路径:

websoctet_lab/cousumer_log_view.py

以上就是python和websocket构建实时日志跟踪器的步骤的详细内容,更多关于python 构建实时日志跟踪器的资料请关注脚本之家其它相关文章!

相关文章

  • pyqt5 使用setStyleSheet设置单元格的边框样式操作

    pyqt5 使用setStyleSheet设置单元格的边框样式操作

    这篇文章主要介绍了pyqt5 使用setStyleSheet设置单元格的边框样式操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • python 关键字与标识符超详细整理

    python 关键字与标识符超详细整理

    这篇文章主要给大家介绍了关于Python关键字、标识符和变量的相关资料,Python关键词是Python保留的具有特定含义的特殊词语,用于执行某些操作,Python标识符是用户定义的名称,而变量是计算机内存中的一块区域,存储对象的内存地址,以便引用对象的值,需要的朋友可以参考下
    2022-03-03
  • pytorch如何自定义forward和backward函数

    pytorch如何自定义forward和backward函数

    PyTorch自动求导功能强大,但在特定情况下需要用户自行定义backward函数,通过实例解释了保存变量、计算梯度、链式法则等核心概念,并展示了如何通过自定义函数集成到网络中以及如何正确返回梯度,此外,还讨论了多输出情况下的梯度传递
    2024-10-10
  • pyqt4教程之messagebox使用示例分享

    pyqt4教程之messagebox使用示例分享

    这篇文章主要介绍了pyqt4的messagebox使用示例,需要的朋友可以参考下
    2014-03-03
  • python爬虫字体加密的解决

    python爬虫字体加密的解决

    本文主要介绍了python爬虫字体加密的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • django 使用 PIL 压缩图片的例子

    django 使用 PIL 压缩图片的例子

    今天小编就为大家分享一篇django 使用 PIL 压缩图片的例子,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-08-08
  • 详解设计模式中的工厂方法模式在Python程序中的运用

    详解设计模式中的工厂方法模式在Python程序中的运用

    这篇文章主要介绍了设计模式中的工厂方法模式在Python程序中的运用,工厂方法模式主张程序在设计时要可以根据不同的条件生成各种类的实例,需要的朋友可以参考下
    2016-03-03
  • Python 的可变和不可变对象详情

    Python 的可变和不可变对象详情

    本文通过详情描述Python 中的可变对象与不可变对象来看两者的区别,刚兴趣的朋友可以参考下文
    2021-08-08
  • 使用python+pandas读写xlsx格式中的数据

    使用python+pandas读写xlsx格式中的数据

    这篇文章主要介绍了使用python+pandas读写xlsx格式中的数据,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下
    2022-08-08
  • python爬虫基础之简易网页搜集器

    python爬虫基础之简易网页搜集器

    这篇文章主要介绍了python爬虫基础之简易网页搜集器,文中有非常详细的代码示例,对正在学习python爬虫的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-04-04

最新评论