Java Design Patterns 之API 网关模式

117 阅读2分钟

API 网关模式

标签

  • 云分布式
  • 解耦
  • 微服务

目的

在单个位置聚合对微服务的多个调用,用户只需要对Api网关调用一次,由网关再对各个微服务发起调用。

解释

在微服务时代,一个表单的展示往往需要多个服务的结果,相应的缺点也就显露出来了:

  • 如果客户端分别调用每个微服务的则会非常耗时
  • 如果涉及的服务发生了变化,则每个使用这个服务的客户端都需要变更

因此为了解决这些问题,则在服务和客户端之间增加了一层,也就是API网关,由网关对客户端所需要调用的服务进行聚合,客户端只需要调用一次网关,剩下的只需要交给网关去调用涉及的微服务即可。

维基百科

API网关就像是前端服务,用于接收前端请求,设置和执行安全策略,将请求转发给后端服务和将响应回复给客户端。API网关可以提供一些数据分析和收集的功能(日志),还有一些缓存的功能,并且可以对认证鉴权安全、审计、合规性校验进行功能支撑。

实战

假设我们的开发的程序有桌面端和手机端两种,商品的浏览界面在桌面端需要展示价格和对应的商品图片,而在手机端则只需要展示商品的价格即可,对应的分别为价格服务和图片服务两个微服务。

如果没有API网关,则客户端需要分配对两种客户端型号做适配,是否调用两个服务,两个服务的地址又是什么;而如果有API网关,则客户端则只需要根据不通的客户端类型调用不同的接口即可,或者传参不同而已,具体的调用逻辑交给网关去做即可。

//图片服务客户端
public interface ImageClient {

    String getImagePath() ;

}

public class ImageClientImpl implements ImageClient{
    public String getImagePath() {
        HttpResponse response = HttpRequest.get("http://localhost:50005/image-path").execute();
        if (response.isOk()) {
            return response.body();
        }
        return null;
    }
}
//价格服务客户端
public interface PriceClient {
    String getPrice();
}

public class PriceClientImpl implements PriceClient{
    public String getPrice() {
        HttpResponse response = HttpRequest.get("http://localhost:50006/price").execute();
        if (response.isOk()) {
            return response.body();
        }
        return null;
    }
}
//桌面产品实体
class DesktopProduct {

    private String imagePath;

    private String price;

}
//手机端产品实体
public class MobileProduct {

    private String price;

}
//API网关
public class ApiGateway {

    @Autowired
    private ImageClient imageClient;

    @Autowired
    private PriceClient priceClient;

    @RequestMapping(path = "/desktop", method = RequestMethod.GET)
    public DesktopProduct getProductDesktop() {
        DesktopProduct desktopProduct = new DesktopProduct();
        desktopProduct.setPrice(priceClient.getPrice());
        desktopProduct.setImagePath(imageClient.getImagePath());
        return desktopProduct;
    }


    @RequestMapping(path = "/mobile", method = RequestMethod.GET)
    public MobileProduct getProductMobile() {
        MobileProduct mobileProduct = new MobileProduct();
        mobileProduct.setPrice(priceClient.getPrice());
        return mobileProduct;
    }
}

参考