【问题标题】:Best way to handle exceptions when the invoked method throws a lot of exception当调用的方法抛出大量异常时处理异常的最佳方法
【发布时间】:2017-12-20 15:31:27
【问题描述】:

我尝试像这样处理 rpc 异常

try {
    rpcService.invokeRemoteMethod(foo)

} catch (Exception e) {
    logger.error("invokeRemoteMethod failed, foo = {} ", foo);
    throw CustomException(e);
}

当rpcService不可用的时候,比如timeout,这段sn-p的代码会往文件里写很多stacktrace日志,可能会消耗很多cup和memory。所以我猜能不能设置一些阈值,例如当同一异常每分钟发生一次时,我打印整个异常堆栈,每分钟 10 次,我只打印异常消息,100 次以上,我什么也不记录。

【问题讨论】:

  • 不要停下来记录错误!在我的十大最可怕的编程错误中,不记录错误是排名第一的。相反,停止调用远程方法一段时间,或者修复你的实现,或者杀死当前线程,或者以世界上一切美好的名义,永远不要忽略异常。它们在飞机驾驶舱或核电站中处于红色警戒状态,它们是潜在致命疾病的症状,不考虑它们是可怕的,将打破世界并打开通往恶魔领域的大门。最多改变日志的级别......
  • 服务平时正常吗?为什么您认为在记录期间需要担心 cpu/内存使用情况?分析器是否指出了问题?
  • @spi 我认为系统可用性比日志记录本身更重要,这就是为什么我们的团队开发了可以动态更新日志级别的有用工具。
  • @AndrewS 您可以说该服务通常不稳定,我们有一个依赖于 100 多个 rpc 服务的 Web 项目。有时 rpc 服务器关闭,这可能会引发很多异常
  • 我真的认为处理这种情况的方法可以是任何事情,但要停止记录错误......你真的试图用最糟糕的解决方案来处理问题。这里需要解决的是rpc服务下线的原因,而不是如何不让别人知道。

标签: java exception logging rpc


【解决方案1】:

在我看来,断路器是控制日志记录的合适模式(如果延迟很高,也可以防止 DOS 服务)。如果连续出现超过 5 个异常(可以是每个服务的配置),则可以打开电路,这样如果远程服务关闭,应用程序就不会调用并记录错误。

根据您的项目,您可以使用开源断路器,也可以使用 AOP 编写简单的断路器或使用断路器包装 RPC 类。

理解的最小例子是

public abstract class CircuitBreaker
{
    private Circuit circuit;

    public CircuitBreaker(){
        circuit = new Circuit();
    }

    public void execute()
    {
        if(circuit.isOpen()) {
            throw CircuitOpenException();
        }

        invokeService();
    }

    protected void recordFailure(){
        circuit.recordFailure();
    }

    protected abstract <T extends Object> T invokeService();
}

public class RPCServiceExecutor extends CircuitBreaker
{
    protected Result invokeService() {
        try {
            Result result = rpcService.invokeRemoteMethod(foo);
            return new Result();
        } catch (Exception e) {
            this.recordFailure();
            logger.error("invokeRemoteMethod failed, foo = {} ", foo);
            throw CustomException(e);
        }
    }
}

当电路打开时不记录异常,当电路关闭时总是记录异常。

更多细节和例子可以参考

https://martinfowler.com/bliki/CircuitBreaker.html

https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/concurrent/CircuitBreaker.html

https://spring.io/guides/gs/circuit-breaker/

希望对您有所帮助。如果您需要更详细的真实示例,请告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2011-09-21
    • 1970-01-01
    • 2016-04-03
    相关资源
    最近更新 更多