利用 MOM消息队列技术实现一个分布式随机信号分析系统

(一)系统架构

本分布式随机信号分析系统采用微服务架构,主要包含三个微服务:随机信号产生器微服务、随机信号统计分析微服务和实时数据显示微服务。各微服务之间通过 RabbitMQ 消息队列进行通信,实现松耦合的分布式协作。

(二)随机信号产生器微服务

实现:每隔一段时间产生一个符合高斯分布的随机数字,并将其作为消息发布到 RabbitMQ 消息队列中。

(三)随机信号统计分析微服务

  1. 功能
    1. 订阅随机信号产生器微服务发布的消息,从消息队列中取出随机信号。
    2. 将取出的随机信号加入维护的数组中。
    3. 计算过去 N 个随机信号的均值和方差(N 为可设置常量)。
    4. 计算所有历史数据中的最大值和最小值。
    5. 将分析结果(均值、方差、最大值、最小值)以空格隔开,打包成字符串形式的消息,发布到 RabbitMQ 消息队列中。

(四)实时数据显示微服务

  1. 功能
    1. 订阅随机信号统计分析微服务发布的消息,获取分析结果。
    2. 实时绘制过去一段时间内随机信号的折线图,展示随机信号的变化趋势。
    3. 实时显示随机信号统计分析结果,包括均值、方差、最大值、最小值等信息。

(五)系统整体流程图

(六)关键代码模块

  1. 随机信号产生器微服务
import pika

import random

import time

# 连接到RabbitMQ服务器

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))

channel = connection.channel()

# 确保队列存在

channel.queue_declare(queue='random_signal_queue')

def generate_random_signal():

    return random.gauss(0, 1)  # 生成一个高斯分布的随机数

def main():

    while True:

        signal = generate_random_signal()

        channel.basic_publish(exchange='',

                              routing_key='random_signal_queue',

                              body=str(signal))

        print(f"Sent: {signal}")

        time.sleep(1)  # 每隔1秒发送一个信号

if __name__ == '__main__':

main()

运行结果如图

 (七)随机信号统计分析微服务

import pika
import matplotlib.pyplot as plt
from random import random
# 连接到RabbitMQ服务器
# 使用pika库的ConnectionParameters来指定连接参数,这里连接到本地的RabbitMQ('localhost')
# 创建一个阻塞式的连接,意味着后续代码执行会等待连接成功或出现错误才继续往下走
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
# 在已建立的连接上创建一个通道,通道是与RabbitMQ进行通信的基本操作单元,例如发布消息、订阅队列等操作都是通过通道来进行的
channel = connection.channel()
# 确保队列存在
# 使用queue_declare方法声明一个名为'random_signal_queue'的队列。如果队列不存在,RabbitMQ会创建它;如果已经存在,则确保它符合期望的配置(例如队列的属性等)
channel.queue_declare(queue='random_signal_queue')
# 存储信号的列表
# 用于后续存储从消息队列中接收到的信号数据,方便进行绘图等操作
signals = []
# 实时绘图函数
def plot_signal():
    """
    这个函数用于实时绘制信号数据的图像。
    它首先检查是否有接收到的信号(即signals列表不为空),如果有:
    1. 清除之前绘制的图像(通过plt.clf()),避免图像重叠混乱。
    2. 使用plt.plot绘制红色线条('r-')来展示信号数据随时间(这里简单以列表索引模拟时间)的变化情况。
    3. 设置图像的标题、x轴标签和y轴标签,用于清晰标识图像内容。
    4. 使用plt.pause暂停一小段时间(0.01秒),这一步很关键,它允许图形界面有时间去更新图像显示,实现实时可视化的效果。
    """
    if signals:
        plt.clf()  # 清除之前的图像
        plt.plot(signals, 'r-')  # 绘制红色线条
        plt.title('Real-time Random Signal Plot')
        plt.xlabel('Time')
        plt.ylabel('Signal Value')
        plt.pause(0.01)  # 暂停一点时间,以便更新图像

# 回调函数,处理接收到的消息
def on_signal_callback(ch, method, properties, body):
    """
    这个回调函数会在从消息队列接收到消息时被自动调用。
    它的参数含义如下:
    - ch: 代表通道对象,这里可以通过它进行一些与消息队列相关的操作,比如确认消息等,但在这个函数里暂时没有使用到这个功能。
    - method: 包含了消息传递的一些方法相关的信息,例如消息的路由键等,这里也未使用。
    - properties: 消息的属性,例如消息的优先级、持久化设置等,同样在这个函数里未使用。
    - body: 消息的实际内容,以字节流的形式存在,这里我们假设消息内容是可以转换为浮点数的信号值。
    函数内部操作:
    1. 将接收到的消息体(body)转换为浮点数类型,作为信号值。
    2. 将这个信号值添加到signals列表中,用于后续的绘图操作。
    3. 调用plot_signal函数,实时绘制包含新接收到信号的图像。
    """
    signal = float(body)
    signals.append(signal)  # 将新信号添加到列表中
    plot_signal()  # 绘制信号图
# 开始监听队列
# 使用basic_consume方法开始订阅名为'random_signal_queue'的队列,指定当有新消息到达时要调用的回调函数(on_signal_callback),
# 并且设置auto_ack为True,表示自动确认消息,即一旦消息被接收并处理(这里就是添加到列表并绘图),就自动告诉RabbitMQ服务器消息已被正确处理。
channel.basic_consume(queue='random_signal_queue',
                      on_message_callback=on_signal_callback,
                      auto_ack=True)
print('Waiting for signals. To exit press CTRL+C')
# 启动消息消费循环,这个方法会阻塞当前线程,让程序一直处于监听队列消息的状态,直到手动按下CTRL+C中断程序或者出现其他异常情况导致连接断开。
channel.start_consuming()

结果打印

(八)实时数据显示微服务 

 import pika
import numpy as np
import time
# 连接到RabbitMQ服务器
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
# 确保队列存在
channel.queue_declare(queue='random_signal_queue')
channel.queue_declare(queue='analysis_result_queue')
N = 10  # 常量N
signals = []  # 存储最近N个信号
def callback(ch, method, properties, body):
    signal = float(body)
    signals.append(signal)
    if len(signals) > N:
        signals.pop(0)  # 保持数组大小为N
    if len(signals) == N:
        mean_val = np.mean(signals)
        var_val = np.var(signals)
        max_val = np.max(signals)
        min_val = np.min(signals)
        analysis_result = f"Mean: {mean_val}, Variance: {var_val}, Max: {max_val}, Min: {min_val}"
        print(analysis_result)
        ch.basic_publish(exchange='',
                         routing_key='analysis_result_queue',
                         body=analysis_result)
channel.basic_consume(queue='random_signal_queue',
                      on_message_callback=callback,
                      auto_ack=True)
print('Waiting for signals. To exit press CTRL+C')
channel.start_consuming()

结果打印

 

问题分析

  1. 问题:消息队列的连接稳定性问题,可能出现连接中断或消息丢失。解决方案:配置 RabbitMQ 的连接参数,增加重连机制,确保在连接异常时能够自动重新连接;同时,设置消息的持久化策略,保证消息在发送到队列后即使服务器重启也不会丢失。
  2. 问题:统计分析算法的性能优化,在处理大量随机信号数据时可能出现计算效率低下的情况。解决方案:采用增量计算的方式,在每次新数据加入时,利用已有的统计结果进行更新,避免重复计算所有数据,提高计算效率。例如,计算均值时,可以使用当前均值和新数据来更新新的均值,而不是重新计算整个数组的总和。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大数据小学僧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值