外部API:API网关 / Backend for Front-End

背景

假设你正在采用微服务架构构建一个在线商城,你正在实现一个产品详情页面。你需要开发不同版本的产品详情的用户界面:

  • 为桌面和移动端浏览器开发的,以HTML5 / Javascript 基础的UI - HTML通过服务端的网站应用程序生成
  • 原生 Android 和 iPhone 客户端 - 这些客户端与服务器通过REST API交互

此外,这个在线商场必须通过 REST API 暴露产品详情接口,给第三方应用程序使用。

产品性行情UI可以展示关于产品的许多信息。比如,Amazon.com 上 POJOs in Action 的详情页展示了:

  • 这本书的基础信息,比如标题,作者,价格,等等。
  • 你的购买历史
  • 可购买
  • 购买选项
  • 与这本书一起被频繁购买的其他商品
  • 这本书的顾客购买的其他商品
  • 顾客评论
  • 销售评分
  • 。。。

由于在线商城采用了微服务架构,产品详情数据散步在多个服务。例如,

  • 产品信息服务 - 产品基础信息,比如标题,作者
  • 价格服务 - 产品价格
  • 订单服务 - 产品购买历史
  • 库存服务 - 产品是否可购买
  • 评论服务 - 顾客评论
  • 。。。

因此,展示产品详情的代码需要从这些服务获取信息。

问题

微服务为基础的应用客户端怎么访问分散的服务?

限制

  • 微服务提供的API粒度,通常与客户端需要的不一样。微服务通常提供细粒度的API,意味着客户端需要与多个服务交互。例如,如上描述的,需要产品详情的客户端需要从很多服务获取数据。
  • 不同的客户端需要不同的数据。比如,桌面浏览器版本的产品详情页通常比移动端版本的更详尽。
  • 不同类型的客户端,网络性能不一样。比如,移动端网络通常比非移动端网络更慢,延迟更高。而且,当然的,任何WAN都比LAN更慢。这意味着原生移动端客户端和使用LAN的服务端网站程序有着完全不同的性能特点。服务端的网络可以对后端服务发起多次请求,不会影响用户体验,但移动端客户端仅仅能发起更少的请求。
  • 服务实例的数量和他们的地址(主机和端口)动态变化
  • 服务的划分可以随着时间而改变,而且应该对客户端隐藏
  • 服务应该可以采用多种协议,其中一些可能不是web友好

解决方案

实现一个API网关,作为所有客户端的单一入口。API网关以两种方式之一处理请求。一部分请求简单的代理 / 路由到对应的服务。其他请求分散给多个服务。

image.png

相比起提供一刀切风格的API,API网关可以对不同的客户端暴露不同的接口。比如,Netflix API网关运行了对特定客户端的适配代码,为不同客户端提供了最适应它们需求的接口。

API网关业务通常实现了安全性,比如验证客户端发起请求时是否经过授权。

变异: Backent for front-end

这个模式的一个变异是 Backend for Front-End 模式。它为不同类型的客户端定义了不同的API网关。

image

在这个例子中,有三种类型的客户端:网站应用程序,移动端应用程序和第三方应用程序。也有三种不同的网关。每个网关为它的客户端提供接口。

示例:

结果

使用API网关有如下优势:

  • 将客户端从应用怎样拆分为微服务中隔离
  • 将客户端从定位服务实例的问题中隔离
  • 为每个客户端提供最优的接口
  • 减少了请求 / 往返的数量。比如,API网关允许客户端从单次往返中获取多个服务的数据。更少的请求,意味着更小的开销,并提升了用户体验。API网关对移动端应用程序是必需的。
  • 简化了客户端,将调用多个服务的逻辑从客户端迁移到了API网关
  • 将标准,公开,web友好的API协议翻译成内部使用的无论什么协议

API网关有如下弊端:

  • 提升了复杂度 - API网关另外一个需要开发,部署和管理的组件
  • 由于通过API网关产生的额外的条数,提升了响应时间 - 然而,对大多数应用来说,额外的一次往返开销是微不足道的。

问题:

  • 如何实现API网关?如果必须扩展为处理高负载,最好的方式事件驱动 / 响应式。在JVM,以NIO为基础的库,比如Netty,Spring Reactor等等是有意义的。NodeJS是另外一个选择。

相关模式

知名案例

示例应用

参考作者的微服务示例应用里的API网关。它采用了Spring Cloud Gateway实现。



作者:scheshan
链接:https://www.jianshu.com/p/9828675c50d2
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
我想将frontend 也是用volumes,将其映射到/app/frontend目录,在/app/frontend下install以及build,如何实现 docker-compose.yml文件: version: '3' services: frontend: build: context: ./frontend dockerfile: Dockerfile ports: - 8010:80 restart: always backend: build: context: ./backend dockerfile: Dockerfile volumes: - /app/backend:/app environment: - CELERY_BROKER_URL=redis://redis:6379/0 command: python manage.py runserver 0.0.0.0:8000 ports: - 8011:8000 restart: always celery-worker: build: context: ./backend dockerfile: Dockerfile volumes: - /app/backend:/app environment: - CELERY_BROKER_URL=redis://redis:6379/0 command: celery -A server worker -l info --pool=solo --concurrency=1 depends_on: - redis - backend restart: always celery-beat: build: context: ./backend dockerfile: Dockerfile volumes: - /app/backend:/app environment: - CELERY_BROKER_URL=redis://redis:6379/0 command: celery -A server beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler depends_on: - redis - backend restart: always redis: image: redis:latest ports: - 6379:6379 restart: always mysql: image: mysql:latest environment: - MYSQL_ROOT_PASSWORD=sacfxSql258147@ ports: - 8016:3306 volumes: - ./mysql:/var/lib/mysql restart: always frontend:dockerfile文件 FROM node:16.18.1 WORKDIR /app/frontend COPY package*.json ./ RUN npm install COPY . . RUN npm run build:prod FROM nginx:latest COPY --from=0 /app/frontend/dist/ /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
07-14

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值