isql 测试mysql连接_[libco] 协程库学习,测试连接 mysql

历史原因,一直使用 libev 作为服务底层;异步框架虽然性能比较高,但新人学习和使用门槛非常高,而且串行的逻辑被打散为状态机,这也会严重影响生产效率。

用同步方式实现异步功能,既保证了异步性能优势,又使得同步方式实现源码思路清晰,容易维护,这是协程的优势。带着这样的目的学习微信开源的一个轻量级网络协程库:libco 。

1. 概述

libco 是轻量级的协程库,看完下面几个帖子,应该能大致搞懂它的工作原理。

2. 问题

带着问题学习 libco:

搞清这几个概念:阻塞,非阻塞,同步,异步,锁。

协程是什么东西,与进程和线程有啥关系。

协程解决了什么问题。

协程在什么场景下使用。

协程切换原理。

协程切换时机。

协程需要上锁吗?

libco 主要有啥功能。(协程管理,epoll/kevent,hook)

3. libco 源码结构布局

将 libco 的源码结构展开,这样方便理清它的内部结构关系。

1aed2774b60e98c377e0c64f28085c19.png

4. mysql 测试

测试目标:测试 libco 协程性能,以及是否能将 mysqlclient 同步接口进行异步改造。

测试系统:CentOS Linux release 7.7.1908 (Core)

测试源码:github。

9f116947723b9334b27753f44a61bfcb.png

4.1. 测试源码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58/* 数据库信息。 */

typedef struct db_s {

std::string host;

int port;

std::string user;

std::string psw;

std::string charset;

} db_t;

/* 协程任务。 */

typedef struct task_s {

int id; /* 任务 id。 */

db_t* db; /* 数据库信息。 */

MYSQL* mysql; /* 数据库实例指针。 */

stCoRoutine_t* co; /* 协程指针。 */

} task_t;

/* 协程处理函数。 */

void* co_handler_mysql_query(void* arg) {

co_enable_hook_sys();

...

/* 同步方式写数据库访问代码。 */

for (i = 0; i < g_co_query_cnt; i++) {

g_cur_test_cnt++;

/* 读数据库 select。 */

query = "select * from mytest.test_async_mysql where id = 1;";

if (mysql_real_query(task->mysql, query, strlen(query))) {

show_error(task->mysql);

return nullptr;

}

res = mysql_store_result(task->mysql);

mysql_free_result(res);

}

...

}

int main(int argc, char** argv) {

...

/* 协程个数。 */

g_co_cnt = atoi(argv[1]);

/* 每个协程 mysql query 次数。 */

g_co_query_cnt = atoi(argv[2]);

/* 数据库信息。 */

db = new db_t{"127.0.0.1", 3306, "root", "123456", "utf8mb4"};

for (i = 0; i < g_co_cnt; i++) {

task = new task_t{i, db, nullptr, nullptr};

/* 创建协程。 */

co_create(&(task->co), NULL, co_handler_mysql_query, task);

/* 唤醒协程。 */

co_resume(task->co);

}

/* 循环处理协程事件逻辑。 */

co_eventloop(co_get_epoll_ct(), 0, 0);

...

}

5. hook

在 Centos 系统,查看 hook 是否成功,除了测试打印日志,其实还有其它比较直观的方法。

5.1. strace

用 strace 查看底层的调用,我们看到 mysql_real_connect 内部的 connect,被 hook 成功,connect 前,被替换为 libco 的 connect 了。socket 在 connect 前,被修改为 O_NONBLOCK 。

1

2

3

4

5# strace -s 512 -o /tmp/libco.log ./test_libco 1 1

socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 4

fcntl(4, F_GETFL) = 0x2 (flags O_RDWR)

fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0

connect(4, {sa_family=AF_INET, sin_port=htons(3306), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now inprogress)

5.2. gdb

上神器 gdb,在 co_hook_sys_call.cpp 文件的 read 和 write 函数下断点。

命中断点,查看函数调用堆栈,libco 在 Centos 系统能成功 hook 住 mysqlclient 的阻塞接口。

1

2

3

4

5

6

7

8

9

10#0 read (fd=fd@entry=9, buf=buf@entry=0x71fc30, nbyte=nbyte@entry=19404) at co_hook_sys_call.cpp:299

#1 0x00007ffff762b30a in read (__nbytes=19404, __buf=0x71fc30, __fd=9) at /usr/include/bits/unistd.h:44

#2 my_read (Filedes=Filedes@entry=9, Buffer=Buffer@entry=0x71fc30 "", Count=Count@entry=19404, MyFlags=MyFlags@entry=0)

at /export/home/pb2/build/sb_0-37309218-1576675139.51/rpm/BUILD/mysql-5.7.29/mysql-5.7.29/mysys/my_read.c:64

#3 0x00007ffff7624966 in inline_mysql_file_read (

src_file=0x7ffff78424b0 "/export/home/pb2/build/sb_0-37309218-1576675139.51/rpm/BUILD/mysql-5.7.29/mysql-5.7.29/mysys/charset.c",

src_line=383, flags=0, count=19404, buffer=0x71fc30 "", file=9)

at /export/home/pb2/build/sb_0-37309218-1576675139.51/rpm/BUILD/mysql-5.7.29/mysql-5.7.29/include/mysql/psi/mysql_file.h:1129

#4 my_read_charset_file (loader=loader@entry=0x7ffff7ed7270, filename=filename@entry=0x7ffff7ed7320 "/usr/share/mysql/charsets/Index.xml",

myflags=myflags@entry=0) at /export/home/pb2/build/sb_0-37309218-1576675139.51/rpm/BUILD/mysql-5.7.29/mysql-5.7.29/mysys/charset.c:383

6. 压测结果

从测试结果看,单进程单线程,多个协程是“同时”进行的,“并发”量也随着协程个数增加而增加,跟测试预期一样。

这里只测试协程的”并发性”,实际应用应该是用户比较多,每个用户的 sql 命令比较少的。

1

2

3

4

5

6

7

8

9

10

11

12

13

14# ./test_libco 1 10000

id: 0, testcnt: 10000, cur spend time: 1.778823

total cnt: 10000, total time: 1.790962, avg: 5583.591448

# ./test_libco 2 10000

id: 0, testcnt: 10000, cur spend time: 2.328348

id: 1, testcnt: 10000, cur spend time: 2.360431

total cnt: 20000, total time: 2.373994, avg: 8424.620726

# ./test_libco 3 10000

id: 0, testcnt: 10000, cur spend time: 2.283759

id: 2, testcnt: 10000, cur spend time: 2.352147

id: 1, testcnt: 10000, cur spend time: 2.350272

total cnt: 30000, total time: 2.370038, avg: 12658.024719

7. mysql 连接池

用 libco 共享栈简单造了个连接池,在 Linux 压力测试单进程 10w 个协程,每个协程读 10 个 sql 命令(相当于 1000w 个包),并发处理能力 8k/s,在可接受范围内。

eea5ec44602de339927cbeda93fc634f.png

1

2# ./test_mysql_mgr r 100000 10

total cnt: 1000000, total time: 125.832877, avg: 7947.048692

压测源码(github)。

mysql 连接池简单实现(github)。

压测发现每个 mysql 连接只能独立运行在固定的协程里,否则大概率会出现问题。

libco hook 技术虽然将 mysqlclient 阻塞接口设置为非阻塞,但是每个 mysqlclient 连接,必须一次只能处理一个命令,像同步那样!非阻塞只是方便协程切换到其它空闲协程进行工作,充分利用原来阻塞等待的时间。而且 mysqlclient 本来就是按照同步的逻辑来写的,一个连接,一次只能处理一个包,不可能被你设置为非阻塞后,一次往 mysql server 发 N 个包,这样肯定会出现不可预料的问题。

libco 协程切换成本不高,主要是 mysqlclient 耗费性能,参考火焰图。

压测频繁地申请内存空间也耗费了不少性能(参考火焰图的 __brk),尝试添加 jemalloc 优化,发现 jemalloc 与 libco 一起用在 Linux 竟然出现死锁!!!

b03dae7c799af29a320620d16e77b5a7.png

8. 小结

通过学习其他大神的帖子,走读源码,写测试代码,终于对协程有了比较清晰的认知。

测试 libco,Centos 功能正常,但 MacOS 下不能成功 Hook 住 mysqlclient 阻塞接口。

libco 是轻量级的,它主要应用于高并发的 IO 密集型场景,所以你看到它绑定了多路复用模型。

虽然测试效果不错,如果你考虑用 libco 去造一个 mysql 连接池,还有不少工作要做。

libco 很不错,所以我选择 golang 🐶。

9. 参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/388918.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是数据仓库,何时以及为什么要考虑一个

The term “Data Warehouse” is widely used in the data analytics world, however, it’s quite common for people who are new with data analytics to ask the above question.术语“数据仓库”在数据分析领域中被广泛使用&#xff0c;但是&#xff0c;对于数据分析新手来…

安装好MongoDB,但服务中没有MongoDB服务的解决办法

以管理员身份打开CMD&#xff0c;添加路径添加服务即可 winX 然后再选Amongod -dbpath "D:\MongoDB\Server\3.6\data\db" -logpath "D:\MongoDB\Server\3.6\data\log\mongo.log" -install -serviceName "MongoDB"转载于:https://www.cnblogs.com…

DRF数据验证+数据存储

1.验证数据的自定义类 class BooksDRFt(serializers.ModelSerializer):class Meta:model Bookfields __all__#要验证的字段author serializers.CharField(requiredFalse)#要验证的字段name serializers.CharField(min_length2, error_messages{required: 不能为空, min_len…

mysql变量 exec_MySQL slave_exec_mode 参数说明

背景&#xff1a;今天无意当中看到参数slave_exec_mode&#xff0c;从手册里的说明看出该参数和MySQL复制相关&#xff0c;是可以动态修改的变量&#xff0c;默认是STRICT模式(严格模式)&#xff0c;可选值有IDEMPOTENT模式(幂等模式)。设置成IDEMPOTENT模式可以让从库避免1032…

C#word

主要功能为根据word模板生成word报表文档,注意引用Interop.Word.dll;首先要生成word程序对象Word.Application app new Word.Application();根据模板文件生成新文件框架File.Copy(TemplateFile, FileName);生成documnet对象ord.Document doc new Word.Document(); 打开…

机器学习kaggle竞赛实战-泰坦尼克号

数据展示 首先登kaggle 下载泰坦尼克训练相关数据 import pandas as pd import numpy as np data pd.read_csv(train.csv) print(data.shape) print(data.head) train data[:800] test data[800:] print(train.shape) print(test.shape)选择特征 selected_features [Pcl…

上海大都会 H.A Simple Problem with Integers

题目描述 You have N integers A1, A2, ... , AN. You are asked to write a program to receive and execute two kinds of instructions: C a b means performing Ai (Ai2 mod 2018) for all Ai such that a ≤ i ≤ b.Q a b means query the sum of Aa, Aa1, ..., Ab. Note…

探索性数据分析入门_入门指南:R中的探索性数据分析

探索性数据分析入门When I started on my journey to learn data science, I read through multiple articles that stressed the importance of understanding your data. It didn’t make sense to me. I was naive enough to think that we are handed over data which we p…

用Javascript代码实现浏览器菜单命令(以下代码在 Windows XP下的浏览器中调试通过

每当我们看到别人网页上的打开、打印、前进、另存为、后退、关闭本窗口、禁用右键等实现浏览器命令的链接&#xff0c;而自己苦于不能实现时&#xff0c;是不是感到很遗憾&#xff1f;是不是也想实现&#xff1f;如果能在网页上能实现浏览器的命令&#xff0c;将是多么有意思的…

mysql程序设计教程_MySQL教程_编程入门教程_牛客网

MySQL 索引MySQL索引的建立对于MySQL的高效运行是很重要的&#xff0c;索引可以大大提高MySQL的检索速度。打个比方&#xff0c;如果合理的设计且使用索引的MySQL是一辆兰博基尼的话&#xff0c;那么没有设计和使用索引的MySQL就是一个人力三轮车。拿汉语字典的目录页(索引)打比…

学习笔记整理之StringBuffer与StringBulider的线程安全与线程不安全

关于线程和线程不安全&#xff1a; 概述 编辑 如果你的代码所在的进程中有多个线程在同时运行&#xff0c;而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的&#xff0c;而且其他的变量的值也和预期的是一样的&#xff0c;就是线程安全的。或者说…

python web应用_为您的应用选择最佳的Python Web爬网库

python web应用Living in today’s world, we are surrounded by different data all around us. The ability to collect and use this data in our projects is a must-have skill for every data scientist.生活在当今世界中&#xff0c;我们周围遍布着不同的数据。 在我们的…

NDK-r14b + FFmpeg-release-3.4 linux下编译FFmpeg

下载资源 官网下载完NDK14b 和 FFmpeg 下载之后&#xff0c;更改FFmpeg 目录下configure问价如下&#xff1a; SLIBNAME_WITH_MAJOR$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF) LIB_INSTALL_EXTRA_CMD$$(RANLIB)"$(LIBDIR)/$(LIBNAME)" SLIB_INSTALL_NAME$(SLI…

C# WebBrowser自动填表与提交

C# WebBrowser自动填表与提交 默认分类 2007-04-18 15:47:17 阅读57 评论0 字号&#xff1a;大中小 订阅 要使我们的WebBrowser具有自动填表、甚至自动提交的功能&#xff0c;并不困难。   假设有一个最简单的登录页面&#xff0c;输入用户名密码&#xff0c;点“登录”…

html中列表导航怎么和图片对齐_HTML实战篇:html仿百度首页

本篇文章主要给大家介绍一下如何使用htmlcss来制作百度首页页面。1)制作页面所用的知识点我们首先来分析一下百度首页的页面效果图百度首页由头部的一个文字导航&#xff0c;中间的一个按钮和一个输入框以及下边的文字简介和导航组成。我们这里主要用到的知识点就是列表标签(ul…

C# 依赖注入那些事儿

原文地址&#xff1a;http://www.cnblogs.com/leoo2sk/archive/2009/06/17/1504693.html 里面有一个例子差了些代码&#xff0c;补全后贴上。 3.1.3 依赖获取 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml;//定义…

asp.net core Serilog的使用

先贴上关于使用这个日志组件的一些使用方法&#xff0c;等有时间了在吧官方的文档翻译一下吧&#xff0c;现在真是没时间。 Serilog在使用上主要分为两大块&#xff1a; 第一块是主库&#xff0c;包括Serilog以及Serilog.AspNetCore&#xff0c;如果导入后一个的话会自动导入前…

在FAANG面试中破解堆算法

In FAANG company interview, Candidates always come across heap problems. There is one question they do like to ask — Top K. Because these companies have a huge dataset and they can’t always go through all the data. Finding tope data is always a good opti…

android webView的缓存机制和资源预加载

android 原生使用WebView嵌入H5页面 Hybrid开发 一、性能问题 android webview 里H5加载速度慢网络流量大 1、H5页面加载速度慢 渲染速度慢 js解析效率 js本身的解析过程复杂、解析速度不快&#xff0c;前端页面设计较多的js代码文件 手机硬件设备的性能 机型多&#xff0c;…

mysql springboot 缓存_Spring Boot 整合 Redis 实现缓存操作

摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载&#xff0c;保留摘要&#xff0c;谢谢&#xff01;『 产品没有价值&#xff0c;开发团队再优秀也无济于事 – 《启示录》 』本文提纲一、缓存的应用场景二、更新缓存的策略三、运行 springboot-mybatis-redis 工程…