Ambassador模式

285 阅读2分钟

意图

在客户端上提供助手服务实例, 并将公共功能从共享资源中剥离.

解释

现实生活中的例子

  远程服务有许多客户端访问它提供的功能. 该服务是一个遗留应用程序, 无法更新. 来自用户的大量请求会导致连接的问题. 请求频率的薪规则应该与延迟检查和客户端日志一起实施.

简单的来说

  使用Ambassador模式, 我们可以实现来自客户端的不太频繁的轮询以及延迟检查和日志记录 大使服务可以被认为是一个进程外代理,它与客户机位于同一位置。此模式可用于以与语言无关的方式卸载常见的客户端连接任务,如监视、日志记录、路由、安全性(如TLS)和恢复模式。它通常用于遗留应用程序或其他难以修改的应用程序,以扩展其网络功能。它还可以使专门的团队实现这些功能。

适用性

使用无法修改或极难修改的遗留远程服务时,Ambassador适用。可以在客户端上实现连接功能,从而无需更改远程服务。 大使为远程服务提供本地接口。 Ambassador在客户端提供日志记录、电路中断、重试和安全性。

典型用例

控制对另一个对象的访问 实现日志记录 机具断路 卸载远程服务任务 方便网络连接

已知用途

用于微服务的Kubernetes本机API网关

相关模式

代理 大使模式 设计分布式系统:可扩展、可靠服务的模式和范例

以上是文档提供解释

谈谈个人的理解, 看到里面的代码, 觉得对自己以后开发很有借鉴 比如: 我通过docker-compose部署服务时, 如何判断服务是否已经启动, 可以通过健康检查接口, 轮询获取以及 接口的重试 都可以这样写

@Slf4j
public class ServiceAmbassador implements RemoteServiceInterface {

  // 重试次数
  private static final int RETRIES = 3;
  // 线程睡眠时间
  private static final int DELAY_MS = 3000;

  ServiceAmbassador() {
  }

  @Override
  public long doRemoteFunction(int value) {
    return safeCall(value);
  }

  private long checkLatency(int value) {
    long startTime = System.currentTimeMillis();
    long result = RemoteService.getRemoteService().doRemoteFunction(value);
    long timeTaken = System.currentTimeMillis() - startTime;

    log.info("Time taken (ms): {}", timeTaken);
    return result;
  }

  /**
   * 安全的调用,如果调用失败就重试n次
   * @param value 调用接口的参数
   * @return 结果
   */
  private long safeCall(int value) {
    long retries = 0;
    long result = FAILURE.getRemoteServiceStatusValue();

    for (int i = 0; i < RETRIES; i++) {
      if (retries >= RETRIES) {
        return FAILURE.getRemoteServiceStatusValue();
      }

      if ((result = checkLatency(value)) == FAILURE.getRemoteServiceStatusValue()) {
        log.info("Failed to reach remote: ({})", i + 1);
        retries++;
        try {
          Thread.sleep(DELAY_MS);
        } catch (InterruptedException e) {
          log.error("Thread sleep state interrupted", e);
          Thread.currentThread().interrupt();
        }
      } else {
        break;
      }
    }
    return result;
  }

}

git地址