请教大家,项目为 .NET Framework 4.6.1,ASP.NET Web API 2,数据库操作使用 Entity Framework,数据库为 SQL Server 2008 R2 以上。
有这种场景,Web API 有一个协议会往同一个数据库的多个表中写入信息。
正常情况下是很快的,但有时候会有一些大查询或者批量导入发生在这个协议使用的表中。由于大查询、批量导入会给这些表加锁。
如果正好有大查询、导入任务执行时,访问该 API 协议,可能无法在几秒内返回。导致调用方那边已经到超时时间,给出了提示,但 Web API 还在执行相关插入任务,并且等锁释放后,数据还会插入成功。
请问有什么办法,能在 Web API 中,为个别或所有的 Action 加上超时时间,当到达这个时间后,终止当前进行的操作并回滚?
我考虑过通过 transaction scope,但这样需要开一个很大的事务,这个事务里既有查询又有INSERT或UPDATE,与事务应该尽可能小相悖
我明白问题的根本不在这,但需要有这样一种防御机制。一旦出现这种问题,需要能尽量避免
谢谢。
双方调整超时时间(每一个网络环节都有设定);
如果时间很久,可以做成任务,一个接口发起任务,一个接口查询任务状态;
办法很多根据自己场景适用选择即可。
谢谢回答~
做两个接口,一个用于发起操作,一个用于查询操作状态这个因为涉及到调用方的修改,不太能推进
现在更希望是,假设调用方都是20s超时,我就让 web api 里所有操作10s内完成不了就回滚,并给调用方返回错误信息
@huhubun: 那这不更简单,计时定时,记录操作。但你http api服务端和客户端需要设定超时时间比如15s。
@花飘水流兮: 计时可以,但怎么做到时间到了回滚呢
@huhubun: 可以终止的函数那么终止(检查结果决定step),不能终止的就等待执行结果并记录step;
有正序执行step,那么反序去恢复现场即可(过程根据场景需要 比如失败尝试n次等等,机器永远没有100%的保障,只能尽可能保障,比如函数执行一半,断电连ups都坏了,如果不坏,运营、运维以及开发的失业人员也就更多了)。
写数据接口收到数据,返回处理中,写入队列处理,
查询状态接口,返回处理状态,
一个任务处理队列中的数据。
谢谢回答~
这样需要变更对接流程,不好推动。更希望是在这个协议内部做改动,不知道有没有办法,谢谢。
@huhubun: 你这个不好处理啊。例如 你在Task里边执行,设置个5秒的超时时间。5秒没执行完就取消,取消就回滚事务。也是可以做的,接口请求超时时间就设置的比这个大一些,例如 6秒超时,
如果你的事务很长了.那你要考虑的不是怎么让这个事务变得不会出问题.
而是该把这个事务拆分开了.
1.长耗时的操作API 应当自己控制超时,而不能依赖客户端的超时设置
2.长耗时的操作API,同步的方式是否合理?业务逻辑是否可拆分下,一个http请求至少应当控制在1-2s内。
3.考虑异步回调的方式
a.调用接口申请长耗时操作,接口内部推送消息队列,返回正在处理
b.消费程序消费队列,执行长耗时操作。执行完成(或者超时)回调客户端接口,返回结果。
或者更简单的方式:api接到请求,起一个线程去异步处理。客户端采用轮询的方式,请求是否处理完成及处理结果。(这种方式会有性能和并发影响)
楼上都把更好的方案说完了, 如果现阶段都不太合适用的话, 那就按照你的思路:
为啥不试下对数据库进行读写分离,主库只写,从库只读