序言
路由是微服务体系结构的一个组成部分。例如 /
可以映射到您的Web应用程序,/api/order
映射到用户服务,/api/product
映射到商店服务。 Zuul 默认和 Ribbon 结合实现了负载均衡的功能。
此文章仅限入门 SpringCloud版本为 Greenwich
2016 年前后基于 NIO 的 Zuul2 开始开发,一直到 2018 年才发布,彼时,市场上类似产品层出不穷,Zuul 已经失去了它的先发优势,Spring Cloud 甚至到现在都没有对 Zuul2 提供支持,Spring Cloud Gateway 等产品的出现和 Zuul2 的频繁跳票,便秘式发布也让 Zuul 走下神坛,逐渐沦落为性能一般,需要被替换的代名词。 好吧,但是基本的生产使用也是没有什么问题的。
使用
首先呢加入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- eureka server-->
<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>
</dependencies>
然后在yml里配置下
# 增加 Zuul 配置
spring:
application:
name: spring-cloud-action-zuul
server:
port: 8080
zuul:
routes:
api-a:
path: /api/order/**
serviceId: spring-cloud-action-server-order
api-b:
path: /api/product/**
serviceId: spring-cloud-action-server-product
eureka:
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}}
hostname: localhost
client:
service-url:
# defaultZone 千万别写成 default-zone
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
在yml中呢 path: /api/order/**
意思就是把 spring-cloud-action-server-order
服务下的接口资源全部代理到 **
。
比如http://spring-cloud-action-server-order/getOrder
就代理到http://api/order/getOrder
然后是启动类
@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
过滤器
假设调用服务需要传递token,那么在网关这里就可以做请求,把那些没有传token的请求统统过滤掉。
/**
* 网关认证过滤器(Demo演示,实际根据自身业务考虑实现)
*
* @author
*/
@Component
public class GatewayZuulFilter extends ZuulFilter {
/**
* per:路由之前,如实现认证、记录调试信息等
* routing:路由时
* post:路由后,比如添加HTTP Header
* error:发生错误时调用
*/
@Override
public String filterType() {
return "pre";
}
/**
* 过滤器顺序,类似@Filter中的order
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。
*/
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String token = request.getParameter("token");
if (token == null) {
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(404);
ctx.setResponseBody("token cannot be empty");
}
return null;
}
}
然后呢在匹配不到路由的时候呢可以去配置一个路由的失败回调器
/**
* @program: spring-cloud-some-project
* @author: fulin
* 配置网关路由失败时的回调
* @create: 2019-10-29 10:26
**/
@Component
public class ServerFeignFallback implements FallbackProvider {
@Override
public String getRoute() {
// ServiceId,如果需要所有调用都支持回退,则 return "*" 或 return null
return null;
}
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
/**
* 网关向 api 服务请求失败了,但是消费者客户端向网关发起的请求是成功的,
* 不应该把 api 的 404,500 等问题抛给客户端
* 网关和 api 服务集群对于客户端来说是黑盒
* @return
* @throws IOException
*/
return new ClientHttpResponse() {****};
}
}
跨域
默认情况下,Zuul将所有跨源请求(CORS)路由到服务。如果您希望Zuul处理这些请求,可以通过提供自定义WebMvcConfigurer 来完成 ,配置这样一个bean就可以了
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST")
.allowedHeaders("*");
}
};
}
此文章仅限入门,切记啊不会用找不到多去官网看文档!