跳到主要内容

如何进行盘古微服务网关开发

· 阅读需 6 分钟
程序员老熊

在上文《如何开发微服务应用》中,已经介绍了如何开发一个微服务应用以及微服务模块之间的互相调用。本文主要讨论如何将微服务发布为 HTTP 接口供前端调用。(HTTP -> Dubbo Provider)

技术实现方案

在盘古开发框架下实现将微服务发布为 HTTP 接口有两种方式。

技术方案选型对比

基于 Spring WebMVC 的接口调用模式

  • 实现原理
    基于 Spring WebMVC,本质上是 Servlet 同步请求机制,依赖 Servlet 容器。
  • Dubbo 集成
    依赖接口 JAR ,通过接口调用 Dubbo 服务。
  • 性能 & 复杂度
    性能高,开发简单,部署运维简单。
  • 其它特性
    • 关于跨域配置、流量控制、鉴权、熔断、白名单等(盘古 Web 模块提供了部分功能)。
    • 提供了Controller聚合层,可一定程度上减少了微服务之间的循环依赖和调用。

基于 Apache ShenYu 的泛化调用模式

  • 实现原理
    基于 Spring Webflex,依赖 Netty 框架或 Servlet 3.1+ 容器。
  • Dubbo 集成
    不依赖接口 JAR,泛化调用 Dubbo 服务。(需要维护接口元数据,有一定的性能损耗)
  • 性能 & 复杂度
    网关自身性能较高(Webflex非阻塞模型)。部署和运维网关系统带来一定的成本。
  • 其它特性
    支持流量控制、鉴权、熔断、可观测性等。
提示

上述是从不同维度简单粗暴的以定性的角度给出了一些比较,结论是孤立且脱离项目背景和业务场景的,仅供参考。采用什么样的开发模式不能一概而论,需要综合实际情况酌情选择。但对于大部分盘古开发项目而言,我们推荐整体性价比较高的方案一。当然,如果您的项目背景适合使用 ShenYu 网关,我们也给出了 详细的集成方案,这也会是一个不错的选择。

编程实战一:基于 Spring WebMVC 的接口调用模式

此种模式基于 SpringMVC 通过 Controller 调用后端 Dubbo 服务。依赖 Servlet 容器,需要引入服务接口包。对于 HTTP 接口层面的鉴权、流控等需求都需要基于拦截器来实现。高可用和性能提升可通过Caddy/Nginx 充当 API 网关 反向代理后端多个 Web 节点实现。

安装相关盘古模块

<dependency>
<groupId>com.gitee.pulanos.pangu</groupId>
<artifactId>pangu-web-spring-boot-starter</artifactId>
</dependency>

本地配置

为便于理解,本文基于本地配置的方式编写。若改为标准的 Nacos 配置中心模式,请参阅:配置中心 章节。

spring.application.name=pangu-examples-webapi-dubbo-service-based
spring.jackson.time-zone=GMT+8

pangu.web.cross-origin=true

dubbo.protocol.name=dubbo
dubbo.protocol.port=-1
dubbo.consumer.timeout=5000
dubbo.registry.address=nacos://${nacos.server-addr}?namespace=${nacos.namespace}
dubbo.consumer.check=false

logging.level.root=INFO

调用微服务接口

可以在任何一个 SpringBean 组件中(针对网关模块而言一般是 Controller 中),引入服务接口后就像本地接口调用一样调用远程服务。Dubbo 将提供高性能的基于代理的远程调用能力,服务以接口为粒度,为开发者屏蔽远程调用底层细节。 如下所示,通过 Cotroller 调用远程服务接口,实现将微服务接口发布为 WebAPI。

DemoController.java
// 注入 Dubbo 服务接口
@Reference(version = "1.0.0", group = "pangu-examples-dubbo-service")
private UserService userService;

/**
* 通过 Spring MVC 将 Duboo 微服务接口发布为 HTTP API
* @return
*/
@RequestMapping("/case1")
public Result<List<UserOut>> case1() {
log.info("call case1...");
UserIn userIn = new UserIn().setUserType("1");
List<UserOut> userOuts = userService.listUserOuts(userIn);
return Result.success(userOuts);
}

启动入口

@EnableDubbo
@SpringBootApplication
public class DubboProviderApplication {
public static void main(String[] args) {
PanGuApplicationBuilder.init(DubboProviderApplication.class).run(args);
}
}

本范例源码

编程实战二:基于 ShenYu 网关的泛化调用模式

详见:盘古开发框架集成 Apache ShenYu 网关