记一次数据库事务导致的服务请求超时问题
【摘要】 在最近的一次业务开发中,遇到一次“离奇”的远程接口响应时间问题。问题可以抽象成下述情况:有两个服务A, 服务B,因为业务需要,服务A需要调用服务B的接口并接受返回参数,代码逻辑大致是:服务A代码:/*** 服务A,请求服务B的接口*////// 其他业务String result = HttpKit.post("http://xxxxx/api/method");///// 其他业务服务B代...
在最近的一次业务开发中,遇到一次“离奇”的远程接口响应时间问题。
问题可以抽象成下述情况:
有两个服务A, 服务B,因为业务需要,服务A需要调用服务B的接口并接受返回参数,代码逻辑大致是:
服务A代码:
/**
* 服务A,请求服务B的接口
*/
///// 其他业务
String result = HttpKit.post("http://xxxxx/api/method");
///// 其他业务
服务B代码:
/**
* 服务B,接受请求,执行并返回
*/
@RequestMapping("/api/method")
public Object method() {
// 执行业务代码
return "执行结果";
}
代码也很简单,就是一些基础的SQL查询与更新。
出现的离奇事情是什么呢?
最开始,服务A总是报错为:请求超时,接口19秒才返回。
嗯,首先猜测大概是服务B中的SQL执行慢吧,于是延长HTTP请求的超时时间设置,19秒返回,那我设置30秒总够了吧。
重新尝试,结果发现:请求超时,接口30秒返回结果。
嗯,大概是SQL不稳定吧,于是,再次延长HTTP请求时间到45秒。
再次尝试,结果发现:仍然超时,接口45秒返回结果。
大抵有一种逆转因果论的味道,我请求多长时间,你就跑多长时间,我也没打断点啊!
既然两者存在这么紧密的联系,肯定是存在某种尚未发现的关联,一步一步寻找吧。
发现,A服务,即服务发起端,远程调用请求位于一个数据库事务执行内部,即:
/**
* 服务A
*/
public void method() {
Transaction {
// 更新数据库
SqlExecute("update table_a set a = 1 WHERE id = 1")
///// 其他业务
String result = HttpKit.post("http://xxxxx/api/method");
///// 其他业务
}
}
而B服务,也需要更新同一个表的同一行:
/**
* 服务B,接受请求,执行并返回
*/
@RequestMapping("/api/method")
public Object method() {
// 执行业务代码
SqlExecute("update table_a set b = 1 WHERE id = 1")
return "执行结果";
}
如此,造成A服务走完整个事务之后,B服务的SQL才可以执行下去,从而造成A把表锁了,而B等着解锁后才能继续执行,而A又在等着B的执行结果才解锁,从而造成上述的局面。
总结
从此,长了一个经验,数据库事业也可能造成远程请求的超时问题。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)