什么是API网关服务?
个人理解:
简单直白点说主要就是为了解决各个微服务应用中的冗余逻辑,比如用户状态校验、签名校验等等,假设一个系统有十个应用服务,每个里面都维护着相同的用户状态校验和签名校验的逻辑,如果发现一个BUG需要需改,那我们还得去十个应用里面挨个修改,这对于后续的维护会产生很大的负担,而且伴随着的是也会对测试工作产生倍数的增长,毕竟每个应用改完都得重新覆盖测试,所以产生了API网关的概念。
所有的外部请求都经过API网关进行调度和过滤,比如我们把用户校验、签名校验的相关逻辑从各个应用中分离出来,单独创建一个应用服务,在API网关上统一调用来对微服务接口做前置过滤。它的存在就像是整个微服务架构的门面一样,所有的外部客户端访问都需要经过它来调度和过滤。主要实现了请求路由、负载均衡、校验过滤、熔断、聚合等等一系列高级功能。
Spring Cloud提供了基于Netflix Zuul实现的API网关组件Spring Cloud Zuul,主要有请求路由、请求过滤、服务路由配置、路径匹配、本地跳转、过滤器、动态加载、Hystrix和Ribbon支持等等功能,太多了,不多啰嗦,本节先看实现一个入门例子,先来了解Spring Cloud Zuul中封装的API网关是怎么使用的,怎么应用到微服务架构中的。
本节先用一个简单的例子,使用服务路由配置
,来实API网关将求转发到具体实例的功能。
- 我们先创建一个接口服务,方便等会测试
1.新建一个Spring Boot工程,命名为zuul-consumer(随意)
2.编辑pom.cml,添加主要依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
3.编辑application.yml
spring:
application:
name: zuul-consumer
server:
port: 9002
eureka:
client:
service-url:
defaultZone: http://peer1:1111/eureka/
4.编辑主类,添加@EnableDiscoveryClient
注解,把该服务注册到注册中心
@SpringBootApplication
@EnableDiscoveryClient
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
5.添加ZuulController,提供一个接口,等会就用这个接口测试
@RestController
@RequestMapping(value = "/zuul")
public class ZuulController {
@GetMapping(value = "/test")
public String feignConsumer() {
System.out.println("zuul测试");
return "zuul测试";
}
}
- 创建API网关服务
1.新建一个Spring Boot工程,命名为zuui-api-gateway(随意)
2.编辑pom.cml,添加spring-cloud-starter-netflix-zuul
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
3.查看spring-cloud-starter-netflix-zuul
包可以看到该包包含了hystrix、ribbon、actuator重要依赖。
spring-cloud-starter-netflix-hystrix
:在网关服务中实现对微服务转发时候的保护机制,通过线程隔离和断路器来防止微服务的故障引发API网关资源无法释放而影响别的应用的对外服务。
spring-cloud-starter-netflix-ribbon
:实现在网关服务中进行路由转发时候的客户端负载均衡和请求重试。
spring-boot-starter-actuator
:提供常规的微服务管理端点。

4.编辑application.yml
spring:
application:
name: zuul-api-gateway
server:
port: 9000
eureka:
client:
service-url:
defaultZone: http://peer1:1111/eureka/
#配置服务路由
zuul:
routes:
zuul-consumer: /zuul-test/**
zuul.routes.zuul-consumer=/zuul-test/**
的作用是配置服务路由
配置方式是zuul.routes.<serviceId>=<path>
。
<serviceId>
代表具体的服务实例地址,不区分大小写image.png
<path>
配置请求的表达式
我们配置文件中的zuul.routes.zuul-consumer=/zuul-test/**
代表将符合/zuul-test/**
规则的请求路径转发zuul-consumer
的服务实例上。
比如请求我们刚刚创建的API网关服务:http://localhost:9000/zuul-test/zuul/test,符合了我们配置的/zuul-test/**
的规则,则API网关会把请求转发到http://localhost:9002/zuul/test。
API网关服务和接口服务都注册到了服务中心,所以API网关可以获取到服务注册中心的所有实例信息,然后可以通过我们刚刚说的<serviceId>
找到服务实例具体的地址。
/zuul-test/**
:**
代表通配符,有三种
?
:匹配任意单个字符,比如可以匹配/zuul-test/a、/zuul-test/b
*
:匹配任意数量的字符,比如/zuul-test/a、/zuul-test/aaa、
**
:匹配任意数量的字符,且支持多级目录,比如/zuul-test/aaa/bbb、/zuul-test/bb/c
5.编辑主类,添加@EnableDiscoveryClient
注解,把该服务注册到注册中心,添加@EnableZuulProxy
注解,开启zuul的API网关服务功能
@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
下面启动服务注册中心(这里就不讲怎么搭建服务注册中心了)、zuul-consumer、zuui-api-gateway三个服务。

可以看到zuul-consumer、zuui-api-gateway两个服务都注册到了服务注册中心。
下面我们访问API服务:http://localhost:9000/zuul-test/zuul/test

正常返回了我们接口服务的
/zuul/test
接口的内容,说明API网关服务根据我们配置的服务路由配置生效了,将http://localhost:9000/zuul-test/zuul/test的请求成功转发到了http://localhost:9002/zuul/test地址。
服务路由配置规则还可以使用
zuul.routes.<route>.path
与zuul.routes.<route>.serviceId
实现
拿我们上面的例子来讲,也可以写成:
zuul.routes.zuul-consumer.path=/zuul-test/**
zuul.routes.zuul-consumer.serviceId=zuul-consumer
还有一点需要注意的是当API网关服务和Eurake整合以后,网关服务会为Eurake中的每个服务都创建一个默认的路由规则,这些默认的规则的path会使用serviceId配置的服务名作为请求前缀,比如我们上面的例子,其实还自动生成了一套路由规则,如下
zuul.routes.zuul-consumer.path=/zuul-consumer/**
zuul.routes.zuul-consumer.serviceId=zuul-consumer
我们可以测试一下,我们清楚的是在配置文件中并没有配置/zuul-consumer/**
的路由规则,现在我们请求一下http://localhost:9000/zuul-consumer/zuul/testimage.png
发现一样请求成功,这样可能会使得一些不希望对外开放的服务也能被外部访问,针对这个问题,我们可以使用ignored-services
来设置哪些服务不自动创建默认路由规则,也可以将ignored-services
设置为*
,对所有服务不创建,然后自己通过我们上面讲的,对我们希望对外提供的服务单独添加路由规则。
测试一下ignored-services,修改zuui-api-gateway工程的application.yml,添加
ignored-services: "*"
zuul:
routes:
zuul-consumer: /zuul-test/**
ignored-services: "*"
重启,然后在访问一下http://localhost:9000/zuul-consumer/zuul/test

可以看到通过默认路由规则已经访问不到了。
网友评论