记一次数据库事务导致的服务请求超时问题

举报
KevinQ 发表于 2022/03/03 17:12:41 2022/03/03
【摘要】 在最近的一次业务开发中,遇到一次“离奇”的远程接口响应时间问题。问题可以抽象成下述情况:有两个服务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

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。