Python/C异步TCP server开发需求:优化MySQL远程写入性能
解决方案:Ubuntu上的异步TCP服务器+MySQL高性能写入实现
针对你遇到的VB.NET TCP服务器配合远程MySQL写入耗时过高的问题,下面分别提供Python和C两种技术栈的异步实现方案,重点解决高并发客户端连接下的数据库写入性能瓶颈。
一、Python方案(快速开发+高并发友好)
Python的asyncio原生支持异步IO,搭配异步MySQL驱动aiomysql可以高效处理1000个客户端的并发请求,同时优化数据库写入性能。
1. 核心实现代码
import asyncio import aiomysql import struct # 数据库配置 DB_CONFIG = { 'host': 'localhost', # 替换为你的MySQL服务器地址 'user': 'your_db_user', 'password': 'your_db_pwd', 'db': 'your_target_db', 'charset': 'utf8mb4', 'maxsize': 20 # 连接池大小,根据并发量调整 } # 处理单个客户端连接 async def handle_client(reader: asyncio.StreamReader, writer: asyncio.StreamWriter): try: # 确保读取完整的160字节数据,避免粘包 data = await reader.readexactly(160) # 解析数据(这里根据你的业务规则自定义解析逻辑) # 示例:前8字节为客户端ID(无符号长整型),剩余为业务内容 client_id = struct.unpack('Q', data[:8])[0] content = data[8:].decode('utf-8').strip() # 异步写入数据库(使用连接池复用连接) async with aiomysql.connect(**DB_CONFIG) as conn: async with conn.cursor() as cur: # 参数化查询避免SQL注入,同时提升执行效率 await cur.execute( "INSERT INTO your_table (client_id, content) VALUES (%s, %s)", (client_id, content) ) # 批量写入场景建议累积N条后再commit,减少事务提交开销 await conn.commit() writer.write(b'Success') await writer.drain() except asyncio.IncompleteReadError: print("客户端发送数据不完整,已断开连接") except Exception as e: print(f"处理请求出错: {str(e)}") finally: writer.close() await writer.wait_closed() # 启动异步TCP服务器 async def main(): server = await asyncio.start_server( handle_client, '0.0.0.0', 8888 # 监听所有网卡,端口可自定义 ) addr = server.sockets[0].getsockname() print(f"异步TCP服务器启动,监听地址: {addr}") async with server: await server.serve_forever() if __name__ == '__main__': asyncio.run(main())
2. 性能优化要点
- 连接池复用:
aiomysql的连接池可以避免每次请求都创建新数据库连接,这是提升写入速度的核心优化点。 - 批量写入:如果客户端请求是批量到达的,可以缓存100-200条请求后,执行
INSERT ... VALUES (...), (...), ...批量插入,大幅减少数据库IO次数。 - MySQL配置调优:
- 调整
innodb_buffer_pool_size为服务器内存的50%-70%,提升缓存命中率 - 关闭
autocommit,手动控制事务提交时机 - 将
innodb_flush_log_at_trx_commit设为2(牺牲少量持久性换写入性能,根据业务需求选择) - 增大
innodb_write_io_threads提升写入线程数
- 调整
二、C方案(极致性能需求)
如果追求极致低延迟和高吞吐量,推荐使用C语言配合Boost.Asio(异步IO框架)和MySQL异步客户端API实现。
1. 核心实现框架(Boost.Asio + MySQL异步写入)
#include <iostream> #include <memory> #include <boost/asio.hpp> #include <mysql/mysql.h> using boost::asio::ip::tcp; // 数据库配置 const char* DB_HOST = "localhost"; const char* DB_USER = "your_db_user"; const char* DB_PASS = "your_db_pwd"; const char* DB_NAME = "your_target_db"; // 客户端会话类 class Session : public std::enable_shared_from_this<Session> { public: Session(tcp::socket socket) : socket_(std::move(socket)) {} void start() { do_read(); } private: void do_read() { auto self(shared_from_this()); // 异步读取160字节数据 boost::asio::async_read(socket_, boost::asio::buffer(data_, 160), [this, self](boost::system::error_code ec, std::size_t /*length*/) { if (!ec) { // 解析数据(自定义业务逻辑) uint64_t client_id = *reinterpret_cast<uint64_t*>(data_); std::string content(data_ + 8, 152); // 异步写入数据库(这里用异步非阻塞API实现真正的异步) async_mysql_insert(client_id, content); do_write(); } else { std::cerr << "读取数据错误: " << ec.message() << std::endl; } }); } void async_mysql_insert(uint64_t client_id, const std::string& content) { // 初始化MySQL异步连接 MYSQL* conn = mysql_init(nullptr); if (!mysql_real_connect_nonblocking(conn, DB_HOST, DB_USER, DB_PASS, DB_NAME, 3306, nullptr, 0)) { std::cerr << "数据库连接失败: " << mysql_error(conn) << std::endl; mysql_close(conn); return; } // 使用预处理语句提升性能和安全性 MYSQL_STMT* stmt = mysql_stmt_init(conn); const char* query = "INSERT INTO your_table (client_id, content) VALUES (?, ?)"; if (mysql_stmt_prepare(stmt, query, strlen(query)) != 0) { std::cerr << "预处理语句失败: " << mysql_stmt_error(stmt) << std::endl; mysql_stmt_close(stmt); mysql_close(conn); return; } MYSQL_BIND params[2]; memset(params, 0, sizeof(params)); params[0].buffer_type = MYSQL_TYPE_LONGLONG; params[0].buffer = &client_id; params[1].buffer_type = MYSQL_TYPE_STRING; params[1].buffer = const_cast<char*>(content.c_str()); params[1].buffer_length = content.length(); if (mysql_stmt_bind_param(stmt, params) != 0) { std::cerr << "绑定参数失败: " << mysql_stmt_error(stmt) << std::endl; mysql_stmt_close(stmt); mysql_close(conn); return; } // 异步执行插入 if (mysql_stmt_execute_nonblocking(stmt) != 0) { std::cerr << "执行插入失败: " << mysql_stmt_error(stmt) << std::endl; } mysql_stmt_close(stmt); mysql_close(conn); } void do_write() { auto self(shared_from_this()); boost::asio::async_write(socket_, boost::asio::buffer("Success", 7), [this, self](boost::system::error_code ec, std::size_t /*length*/) { if (!ec) { socket_.close(); } }); } tcp::socket socket_; char data_[160]; }; // TCP服务器类 class Server { public: Server(boost::asio::io_context& io_context, short port) : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) { do_accept(); } private: void do_accept() { acceptor_.async_accept( [this](boost::system::error_code ec, tcp::socket socket) { if (!ec) { std::make_shared<Session>(std::move(socket))->start(); } do_accept(); }); } tcp::acceptor acceptor_; }; int main() { try { boost::asio::io_context io_context; Server server(io_context, 8888); io_context.run(); } catch (std::exception& e) { std::cerr << "服务器异常: " << e.what() << std::endl; } return 0; }
2. 编译与优化
- 编译命令(需提前安装Boost和MySQL开发库):
g++ -std=c++17 tcp_server.cpp -o tcp_server -lboost_system -lmysqlclient -pthread - 性能优化建议:
- 实现数据库连接池:复用数据库连接,避免频繁建立连接的开销
- 使用MySQL异步非阻塞API:确保数据库操作不会阻塞IO线程
- 批量写入:缓存多条请求后批量插入,减少数据库交互次数
- 操作系统调优:调整TCP参数(如
net.core.somaxconn、tcp_tw_reuse)提升并发连接处理能力
通用测试建议
- 使用
wrk或tcpcopy工具模拟1000个并发客户端发送请求,测试服务器吞吐量和写入延迟 - 开启MySQL慢查询日志,定位写入操作的性能瓶颈
- 根据业务需求选择方案:Python适合快速迭代,C适合极致性能场景
内容的提问来源于stack exchange,提问作者davidsd
相关产品推荐
相关产品推荐

