python:多线程写入数据到数据库
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
代码功能
以多线程的方式一边读取容器占用cpu和内存资源一边将获得的数据写入数据库
完整代码如下
"""
******************************************************************************************
* 多线程写入数据库-最终版
*-----------------------------------------------------------------------------------------
* 注意pymysql多线程读写数据库报错Packet sequence number wrong
* 解决方法 每个execute前加上互斥锁
* lock.acquire()
* cursor.execute(command,data)
* lock.release()
*
******************************************************************************************
"""
import pymysql.cursors
import threading
import time
import docker
# -------------------------- 初始化 -------------------------------
print('程序初始化...')
print('建立数据库连接...')
# 创建数据库连接
cnx = pymysql.connect(host='localhost', port=3306, user='root', password='123456', db='qt', charset='utf8mb4',connect_timeout=20)
cursor = cnx.cursor()
# 定义容器名列表
container_names = ['a','b','c','d','e','f','g']
# 创建锁
lock = threading.Lock()
# -------------------------- docker stats读取 -------------------------------
def get_container_stats(container_name):
client = docker.from_env() # 假设你已经初始化了 Docker 客户端
container = client.containers.get(container_name)
stats = container.stats(stream=False)
cpu_usage = 100 * stats['cpu_stats']['cpu_usage']['total_usage'] / stats['cpu_stats']['system_cpu_usage']
memory_used = 100 * stats['memory_stats']['usage'] / stats['memory_stats']['limit']
return cpu_usage, memory_used
# -------------------------- 数据库写入 -------------------------------
def mysql_data_update(container_name, cursor, cnx):
cpu_usage, memory_used = get_container_stats(container_name)
# 将容器状态写入数据库
# 执行更新数据的 SQL 语句
lock.acquire()
cursor.execute("UPDATE container_stats SET cpu_usage = %s, memory_used = %s WHERE container_name = %s", [cpu_usage, memory_used, container_name])
# 提交事务
cnx.commit()
lock.release()
print('容器{} 成功写入数据库'.format(container_name))
# -------------------------- 多线程 ------------------------------------
def refresh_stats(container_names, interval=1):
while True:
start_time = time.time()
# 创建线程列表
threads = []
# 多线程1读取容器cpu,mem
for container_name in container_names:
# 创建并启动线程
thread = threading.Thread(target=mysql_data_update, args=(container_name, cursor, cnx))
thread.start()
threads.append(thread)
# 等待所有线程结束
for thread in threads:
thread.join()
end_time = time.time()
total_time = end_time - start_time
print("总时间: {:.2f} 秒".format(total_time))
print("---------------------------------------------------------------------------------------------\n")
time.sleep(interval)
# 调用函数进行实时刷新
refresh_stats(container_names)
代码解释
-
引入所需的模块
pymysql.cursors
用于数据库连接和操作threading
用于多线程操作time
用于时间相关的操作docker
用于与 Docker 进行交互。 -
get_container_stats
函数该函数通过 Docker 客户端获取指定容器的 CPU 和内存使用情况。 -
mysql_data_update
函数该函数用于将容器的 CPU 和内存使用情况写入数据库。它首先调用get_container_stats
函数获取容器的使用情况然后执行 SQL 语句将数据更新到数据库中。 -
refresh_stats
函数该函数是多线程的核心部分。它使用一个无限循环来定期刷新容器的状态。在每次循环中它创建多个线程来处理不同的容器并调用mysql_data_update
函数将容器的使用情况写入数据库。每个线程负责一个容器的处理。线程创建后它们被添加到线程列表中并在循环结束时等待所有线程执行完毕。之后程序会休眠一段时间由interval
参数指定然后再次开始新的循环。
注意
for container_name in container_names
是一个循环语句它用于遍历一个名为container_names
的列表或可迭代对象中的每个元素并将每个元素赋值给变量container_name
。在这段代码中
container_names
是一个包含容器名字的列表。通过使用循环语句程序可以逐个遍历container_names
列表中的容器名字并将每个容器名字赋值给变量container_name
。在循环的每次迭代中程序可以对每个容器执行相应的操作或处理。换句话说这个循环用于迭代处理
container_names
列表中的容器名字以便在后续代码中使用这些容器名字执行相应的操作。
同时代码中使用了互斥锁
lock
来确保在执行cursor.execute
语句时的线程安全性以避免出现报错"Packet sequence number wrong"。在执行cursor.execute
之前获取锁lock.acquire()
在执行完毕后释放锁lock.release()
。