我的服务是DService,我是服务链中的第四个链接,即呼叫流程 在线用户 - > AService - > BService - > CService - > DService - >电子服务
当我从DService调用EService时,它会抛出可重复的异常,如HttpTimeoutException。我通常会重试2-3次,如果在重试2-3次后仍然失败,则会抛出异常。
我的问题是,我向CService抛出的例外情况应该是可重复的还是不可重复的?请在下面找到我对Pros& amp;的评价。两个选项的缺点
从DService投掷可回复异常的缺点 - 如果DService引发可重试的异常,遵循相同的约定CService也可能重试DService 2-3次,并且在每次C-D呼叫中,D将再次尝试2-3次E服务呼叫。同样,随着我们进入呼叫链,最终到EService的呼叫将呈指数级增长。因此,如果EService网络确实长时间停机,我们正在讨论大量不必要的呼叫。这可以通过为链中的每个呼叫设置超时来缓解,但仍然不确定这是否足以缓解不必要的呼叫次数。
从DService投掷可回复异常的优点 - CService将在一段时间后重试,因为在后续重试中我们可能会获得正确的值(在时间限制内) - 特别是如果客户端是一些后端工作,那么他们可以在放弃之前长时间指数重试。抛出Un-Retriable异常将清除此选项
请提供您对此的看法和建议
谢谢, 哈里什
答案 0 :(得分:3)
在不知道服务是做什么的情况下,无论DService是否应该重试或者CService应该重做,我都不能肯定地说。但是我的理念是被调用的服务不应该重试,永远。在这种情况下,EService会愚蠢地抛出异常而无需任何处理。这背后的原因是因为链的末端应该是无状态的,不应该代表调用者做出决定。
呼叫者可以在一定程度上规定可接受的内容以及是否应该重新尝试错误的内容。换句话说,如果EService尝试执行与数据库的连接并且DService正在执行查找服务,则可能在DService的范围内,如果在某个表中找不到某个信息,则可能检查另一张表。但是,EService无法连接到数据库的过程远远落后于DService,其范围只是返回CService请求的信息。
CService根据其操作调用了某些信息,然后可能会收到数据库连接并尝试在延迟后重试多次,因为它正在对该数据执行批处理工作并将继续重试,直到数据库重新联机。或者,如果它正在检索要在网页上向用户显示的信息,则必须快速失败并通过向用户显示一条漂亮的错误消息来处理数据库连接错误。
这完全取决于您的服务以及他们的责任所在。同样,异常是否可以重复应再次取决于呼叫者的必要性,而不是服务本身。向调用者提供可重试的异常是完全可行的,只能尝试一次。
希望有所帮助!
答案 1 :(得分:2)
如果您在链上定义指数增加的重试周期,我认为抛出可重复的异常是一种可行的方法。
答案 2 :(得分:1)
我说你不应该首先在DService中重试,因为正如你所说,如果每项服务都这样做,你可能会遇到麻烦。因此,让异常冒泡到调用堆栈并让它在最外面的服务处理;甚至可能是用户。
理由:为什么在DService上决定CService,BService或AService是否想要重试?
但是,我认为这也取决于例外的频率和重试的成功率。如果异常经常发生,但是通常在第一次或第二次重试时成功,那么除了每天发生一次的异常和/或重试在大多数情况下徒劳无功之外,这是另一回事。
答案 3 :(得分:1)
你向你的召唤者扔了什么,以及你扔给他们的是否也会提出“你可以重试这个”的建议,应该由你的服务的预期语义决定只
(此外,我从未听说过正式携带任何此类属性的java异常对象,但这可能是因为我落后了一点。)
EDIT。
你“重试”失败的操作,是你(并且你自己)决定的。但是,如果您决定重试,那么您还有责任决定在多少次失败后停止重试并在一天内调用它,此时向您的调用者抛出异常是绝对不明智的他也可以“重试”。