当被调用的方法抛出大量异常时,处理异常的最佳方法

时间:2017-12-20 15:31:27

标签: java exception logging rpc

我尝试像这样处理rpc异常

try {
    rpcService.invokeRemoteMethod(foo)

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

当rpcService不可用时,例如超时,这段代码会将大量的堆栈跟踪日志写入文件,这可能会消耗大量的杯子和内存。所以我猜我是否可以设置一些阈值,比如当同样的异常诅咒每分钟一次时,我打印整个异常堆栈,每分钟10次,我只是打印异常消息,100次以上,我没有记录任何内容。

1 个答案:

答案 0 :(得分: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/

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