Mysql 对ruby REST API的并发请求不可能

Mysql 对ruby REST API的并发请求不可能,mysql,ruby,concurrency,sinatra,Mysql,Ruby,Concurrency,Sinatra,我正在尝试使用ruby和运行在瘦服务器上的SinatraGem创建一些小型RESTAPI。重点是了解构建由microweb服务组成的restapi有多容易/难,并将其与Amazon的AWS上提供的其他编程语言/技术进行比较。我已经很容易地创建了一个,这里的代码只是最小的工作项目,还没有考虑任何类型的优化: 需要“sinatra” 需要“mysql” 需要“json” 环境,发展 db\u host='host\u URL' db_user='user' db_pass='密码' db_名称='d

我正在尝试使用ruby和运行在瘦服务器上的SinatraGem创建一些小型RESTAPI。重点是了解构建由microweb服务组成的restapi有多容易/难,并将其与Amazon的AWS上提供的其他编程语言/技术进行比较。我已经很容易地创建了一个,这里的代码只是最小的工作项目,还没有考虑任何类型的优化:

需要“sinatra” 需要“mysql” 需要“json” 环境,发展 db\u host='host\u URL' db_user='user' db_pass='密码' db_名称='db_名称' db_enc='utf8' 选择='从表1中选择*限制30' db=Mysql.init db.options Mysql::SET\u CHARSET\u NAME,db\u enc db=db.real\u connect db\u host、db\u user、db\u pass、db\u name 得到“/品牌”做什么 rs=db.query选择 db.close 结果=[] rs.每行| 结果:推行 终止 result.to_json 终止 使用ruby my_ws.rb运行此命令将启动Sinatra在瘦主机上运行,没有问题

从我的终端使用curl,比如curl-get localhost:4567/brands,也可以返回所需的JSON响应

我现在要解决的真正问题已经持续了几个小时,在谷歌上搜索当然,这里也阅读了大量的资源,所以当我尝试使用Sakege对更多并发用户测试micro WS时:

苏多攻城-b-c2-r2

这应该在benchnark模式下运行,发出2个并发请求-c2开关2次-r2开关。在这种情况下,我总是在控制台中得到一个错误,声明Mysql::ProtocolError-无效数据包:序列号不匹配102!=2预期:虽然每次跑步时102号总是不同的。如果我只为一个用户运行一个并发请求的基准测试,也就是说,完全没有并发性,那么我甚至可以运行它1000次而没有错误sudo-bhttp://localhost:4567/brands -c1-r1000

我尝试在代码中添加手动线程,如:

得到“/品牌”做什么 th=线程。新do rs=db.query选择 db.close 结果=[] rs.每行| 结果:推行 终止 result.to_json 终止 加入 th值 终止 但是没有帮助

根据我的发现:

默认情况下,Sinatra是多线程的 如果由ruby script.rb运行,那么thin也可以从Sinatra运行 多线程似乎对DB查询没有影响-这里看起来不可能有并发 我使用的是ruby mysql gem,因为我发现它比mysql gem更新,但最终我不知道该使用哪一个。我发现旧文章使用mysql,而其他一些文章使用ruby mysql


你知道如何对我的RESTAPI运行并发请求吗?我需要对它进行基准测试,并与其他语言PHP、Python、Scala等进行比较。

问题通过两个修复程序得到解决

第一个是用mysql2替换mysql适配器

第二个问题是问题的真正原因:MySQL连接在运行时创建了一次,之后我甚至可以深入到线程中,即在执行路由代码之前,导致逻辑连接锁定

现在,有了mysql2,在路由执行的情况下连接到DB,即使是250个并发请求,也可以正常工作!最终代码:

需要“sinatra” 需要“mysql2” 需要“json” 环境,发展 db\u host='host\u URL' db_user='user' db_pass='密码' db_名称='db_名称' db_enc='utf8' 选择='从表1中选择*限制30' 得到“/品牌”做什么 结果=[] Mysql2::Client.new:host=>db_host,:username=>db_user,:password=>db_pass,:database=>db_name,:encoding=>db_enc.queryselect.each do|行| 结果:推行 终止 result.to_json 终止 运行sudo攻城-bhttp://localhost:4567/brands -c250-r4现在给了我:

Transactions:             1000 hits
Availability:             100.00 %
Elapsed time:             1.54 secs
Data transferred:         2.40 MB
Response time:            0.27 secs
Transaction rate:         649.35 trans/sec
Throughput:               1.56 MB/sec
Concurrency:              175.15
Successful transactions:  1000
Failed transactions:      0
Longest transaction:      1.23
Shortest transaction:     0.03

我会尝试一个不同的mysql适配器,也许它不是线程安全的。你使用什么ruby运行时?应该是最新的,ruby-v给了我ruby 2.1.2p95 2014-05-08[x86_64-linux-gnu]。我应该尝试其他哪些适配器?纯mysql在设置字符集和编码转换方面存在问题。这就是我用ruby mysql取代它的原因,ruby mysql在版本2.9.13中。我一直使用它,它是一个非常活跃的项目。有些东西丢失了,比如没有准备声明是的,直接查看GH上的mysql2。。。我试试看,然后再查。