在 Java 中使用动态代理处理 API 节流异常

问题描述

我到处都在使用 AWS SSM 客户端,我很难在各处添加 try/catch 块并实现相同的自动重试机制。

有简单的方法吗?

解决方法

是的!我最近在 Java 中发现了代理,我可以用它代理 SSM 客户端中的所有方法,然后到处传递这个代理实例。这是我想出的:

private AWSSimpleSystemsManagement createClient() {
    final AWSSimpleSystemsManagement ssm = AWSSimpleSystemsManagementClientBuilder.standard()
            ...
            ...
            .build();
    return (AWSSimpleSystemsManagement) Proxy.newProxyInstance(ssm.getClass().getClassLoader(),new Class[]{AWSSimpleSystemsManagement.class},(proxy,method,args) -> {
                while (true) {
                    try {
                        return method.invoke(ssm,args);
                    } catch (Exception e) {
                        if (ExceptionUtils.getStackTrace(e).contains("Rate exceeded")
                                || e.toString().contains("Rate exceeded")) {
                            final long delay = (long) (5_000 * Math.random());
                            logger.warn("AWS is throttling us. Will retry in {} ms",delay);
                            EDUtils.sleep(delay);
                        } else {
                            throw e;
                        }
                    }
                }
            });
}

可以在此处找到 InvocationHandler 和 Proxy 的 Javadoc:https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Proxy.html