Netflix Zuul
- Zuul是由netflix开源的API网关,提供动态路由,监控,弹性,安全等边缘服务的框架。Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的前门。
- 具备负载均衡的作用
- 本质上是一个web servlet应用。Zuul是通过Servlet来实现的,Zuul通过定义了ZuulServlet(类似SpringMVC的DispatcherServlet)来对请求进行控制。
- Zuul的核心是一系列的filters, 在Http请求的发起和响应返回期间执行一系列过滤器操作。
搭建Zuul服务
pom.xml 添加jar包依赖
- spring-cloud-starter-netflix-zuul
- spring-cloud-starter-netflix-eureka-client
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
</dependencies>
配置application.properties
- zuul.routes.provider.path :指定请求URL中路由匹配的path规则,匹配到之后指定路由
- zuul.routes.provider.url :路由到的地址(建议,基于微服务可以利用ServiceId,路由具体的服务)
- zuul.routes.provider.serviceId :Spring.application.name 路由到具体的服务
spring.application.name=gateway-service-zuul
server.port=8888
eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
zuul.routes.provider.path=/provider/**
zuul.routes.provider.serviceId=spring-cloud-eureka-provider
启动类开启Zuul
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
为了调试,搭建Provider
- 由于之前有篇幅提供了Provider的搭建,基于之前的笔记搭建的服务就可以了
- 这边只列出几个关键点,便于看的明白
配置application.yml
- 配置3个节点
- 2个服务,其中1个服务2节点集群,另外一个服务单台
spring:
application:
name: spring-cloud-eureka-provider
profiles: provider1
server:
port: 9000
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8000/eureka/
---
spring:
application:
name: spring-cloud-eureka-provider
profiles: provider2
server:
port: 9001
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8000/eureka/
---
spring:
application:
name: spring-cloud-eureka-provider-ha
profiles: provider3
server:
port: 9002
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8000/eureka/
提供的服务
@RestController
@RequestMapping("/")
public class IndexController {
@Value("${spring.profiles}")
private String profile;
@Value("${spring.application.name}")
private String appName;
@RequestMapping("/hello")
public String hello(String name) {
StringBuilder result = new StringBuilder();
result.append("hello:").append(name).append("<br/>");
result.append("profile:").append(profile).append("<br/>");
result.append("appName:").append(appName);
return result.toString();
}
}
启动调试
启动完成,注册服务
- 一个Zuul服务
- 3个Provider节点,2个是同AppName集群,1个是另外的AppName
调试
- 访问路径带上了path指定的规则,Zuul匹配到了之后,就会转到对应的Provider处理
- 因为是集群,多次请求会在集群中切换;说明Zuul具有负载均衡的作用;Zuul是集成了Ribbon实现了负载均衡。
- Zuul默认配置:如果没有配置路由规则,直接路径上带上AppName的服务名,默认路由到对应的服务
搭建完成,测试通过,可见Zuul提供服务的路由功能。
Zuul 路由熔断
- Zuul作为Netflix的组件,可以与Hystrix结合实现熔断器的功能
声明FallbackProvider 来集成熔断功能
- 实现FallbackProvider接口;
- 实现getRoute() 指定熔断的服务;如果适用全部的话 return “*”
- 实现getStatusCode() 方法 ,指定服务不可用之后的逻辑
@Component
public class FuseFallbackProvider implements FallbackProvider {
@Override
public String getRoute() {
return "spring-cloud-eureka-provider";
}
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
}
@Override
public int getRawStatusCode() throws IOException {
return HttpStatus.OK.value();
}
@Override
public String getStatusText() throws IOException {
return HttpStatus.OK.getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
String result = "Fuse ,Fall back; server is error!";
return new ByteArrayInputStream(result.getBytes("UTF-8"));
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
return httpHeaders;
}
};
}
}
启动调试
- 增加FallbackProvider之后重启Zuul服务的应用
- 将上面的AppName:spring-cloud-eureka-provider的Provider停掉一台
- 访问:http://127.0.0.1:8888/provider/hello?name=yanbin
- provider1 继续可以访问
- provider2 熔断,返回默认结果
- 将spring-cloud-eureka-provider-ha 服务停掉
- 访问http://127.0.0.1:8888/spring-cloud-eureka-provider-ha/hello?name=yanbin