2.6 API Gateway

API Gateway是微服务架构中不可或缺的部分。API Gateway的定义以及存在的意义,Chris已经为大家描述过了,本文不再赘述,以下是链接:

中文版:http://dockone.io/article/482

英文版:https://www.nginx.com/blog/building-microservices-using-an-api-gateway/

使用API Gateway后,客户端和微服务之间的网络图变成下图:

API Gateway

通过API Gateway,可以统一向外部系统提供REST API。Spring Cloud中使用Zuul作为API Gateway。Zuul提供了动态路由、监控、回退、安全等功能。

下面我们进入Zuul的学习:

准备工作

  • 为了更贴近生产,我们首先配置Host
  1. 127.0.0.1 gateway
  • 启动服务:microservice-discovery-eureka
  • 启动服务:microservice-provider-user

Zuul代码示例

创建Maven项目,在pom.xml中添加如下内容:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <artifactId>microservice-api-gateway</artifactId>
  6. <packaging>jar</packaging>
  7. <parent>
  8. <groupId>com.itmuch.cloud</groupId>
  9. <artifactId>spring-cloud-microservice-study</artifactId>
  10. <version>0.0.1-SNAPSHOT</version>
  11. </parent>
  12. <dependencies>
  13. <dependency>
  14. <groupId>org.springframework.cloud</groupId>
  15. <artifactId>spring-cloud-starter-zuul</artifactId>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework.cloud</groupId>
  19. <artifactId>spring-cloud-starter-eureka</artifactId>
  20. </dependency>
  21. </dependencies>
  22. </project>

启动类:

  1. /**
  2. * 使用@EnableZuulProxy注解激活zuul。
  3. * 跟进该注解可以看到该注解整合了@EnableCircuitBreaker、@EnableDiscoveryClient,是个组合注解,目的是简化配置。
  4. * @author eacdy
  5. */
  6. @SpringBootApplication
  7. @EnableZuulProxy
  8. public class ZuulApiGatewayApplication {
  9. public static void main(String[] args) {
  10. SpringApplication.run(ZuulApiGatewayApplication.class, args);
  11. }
  12. }

配置文件:application.yml

  1. spring:
  2. application:
  3. name: microservice-api-gateway
  4. server:
  5. port: 8050
  6. eureka:
  7. instance:
  8. hostname: gateway
  9. client:
  10. serviceUrl:
  11. defaultZone: http://discovery:8761/eureka/

这样,一个简单的API Gateway就完成了。

测试

启动microservice-api-gateway项目。还记得我们之前访问通过http://localhost:8000/1去访问microservice-provider-user服务中id=1的用户信息吗?

我们现在访问http://localhost:8050/microservice-provider-user/1试试。会惊人地看到:

  1. {"id":1,"username":"Tom","age":12}

这不正是microservice-provider-user服务中id=1的用户信息吗?

所以我们可以总结出规律:访问

  1. http://GATEWAY:GATEWAY_PORT/想要访问的Eureka服务id的小写/**

,将会访问到

  1. http://想要访问的Eureka服务id的小写:该服务端口/**

自定义路径

上文我们已经完成了通过API Gateway去访问微服务的目的,是通过

  1. http://GATEWAY:GATEWAY_PORT/想要访问的Eureka服务id的小写/**

的形式访问的,那么如果我们想自定义在API Gateway中的路径呢?譬如想使用

  1. http://localhost:8050/user/1

就能够将请求路由到http://localhost:8000/1呢?

只需要做一点小小的配置即可:

  1. spring:
  2. application:
  3. name: microservice-api-gateway
  4. server:
  5. port: 8050
  6. eureka:
  7. instance:
  8. hostname: gateway
  9. client:
  10. serviceUrl:
  11. defaultZone: http://discovery:8761/eureka/
  12. # 下面整个树都非必须,如果不配置,将默认使用 http://GATEWAY:GATEWAY_PORT/想要访问的Eureka服务id的小写/** 路由到:http://想要访问的Eureka服务id的小写:该服务端口/**
  13. zuul:
  14. routes:
  15. user: # 可以随便写,在zuul上面唯一即可;当这里的值 = service-id时,service-id可以不写。
  16. path: /user/** # 想要映射到的路径
  17. service-id: microservice-provider-user # Eureka中的serviceId

如何忽略某些服务

准备工作

  1. 启动服务:microservice-discovery-eureka
  2. 启动服务:microservice-provider-user
  3. 启动服务:microservice-consumer-movie-ribbon

如果我们现在只想将microservice-consumer-movie-ribbon服务暴露给外部,microservice-provider-user不想暴露,那么应该怎么办呢?

依然只是一点小小的配置即可:

  1. spring:
  2. application:
  3. name: microservice-api-gateway
  4. server:
  5. port: 8050
  6. eureka:
  7. instance:
  8. hostname: gateway
  9. client:
  10. serviceUrl:
  11. defaultZone: http://discovery:8761/eureka/
  12. zuul:
  13. ignored-services: microservice-provider-user # 需要忽视的服务(配置后将不会被路由)
  14. routes:
  15. movie: # 可以随便写,在zuul上面唯一即可;当这里的值 = service-id时,service-id可以不写。
  16. path: /movie/** # 想要映射到的路径
  17. service-id: microservice-consumer-movie-ribbon-with-hystrix # Eureka中的serviceId

这样microservice-provider-user服务就不会被路由,microservice-consumer-movie-ribbon服务则会被路由。

测试结果:

URL 结果 备注
http://localhost:8050/microservice-provider-user/1 404 说明microservice-provider-user未被路由
http://localhost:8050/movie/ribbon/1 {“id”:1,”username”:”Tom”,”age”:12} 说明microservice-consumer-movie-ribbon被路由了。

使用Zuul不使用Eureka

Zuul并不依赖Eureka,可以脱离Eureka运行,此时需要配置

  1. spring:
  2. application:
  3. name: microservice-api-gateway
  4. server:
  5. port: 8050
  6. zuul:
  7. routes:
  8. movie: # 可以随便写
  9. path: /user/**
  10. url: http://localhost:8000/ # path路由到的地址,也就是访问http://localhost:8050/user/**会路由到http://localhost:8000/**

我们可尝试访问http://localhost:8050/user/1 ,会发现被路由到了http://localhost:8000/1 。不过在大多数情况下,笔者并不建议这么做,因为得手动大量地配置URL,不是很方便。

其他使用

Zuul还支持更多的特性、更多的配置项甚至是定制开发,具体还请读者自行发掘。

同类软件

Zuul只是API Gateway的一种实现,可作为API Gateway的软件有很多,譬如Nginx Plus、Kong等等,本文不做赘述了。

参考文档

https://www.nginx.com/blog/building-microservices-using-an-api-gateway/
http://microservices.io/patterns/apigateway.html