1.服务网关和zuul
1.服务网关的要素:稳定性,高可用。性能,并发性。安全性。扩展性。
2.常用网关方案:Nginx+Lua,Kong,Tyk,Spring Cloud Zuul
3.zuul特点:路由+过滤器=Zuul,核心是一系列的过滤器
4.四种过滤器API:
前置(Pre) :限流,鉴权,参数校验,请求转发
路由(Route)
后置(Post): 统计
错误(Error)
2.路由转发,排除和自定义
1.导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
2.主类加注解@EnableZuulProxy
3.配置bootstrap.yml
zuul:
routes:
# myProduct: #任意字符都可以
# path: /myProduct/**
# serviceId: product
product: /myProduct/** #路由自定义(简洁方式)
ignored-patterns:
- /**/product/listForOrder #排除某些路由
sensitive-headers: #开放cookie
management:
endpoints:
web:
exposure:
include: "*" #/autuator/routes查看所有路由信息
3.动态路由
@Component
public class ZuulConfig {
@RefreshScope
@ConfigurationProperties("zuul")
public ZuulProperties zuulProperties(){
return new ZuulProperties();
}
}
4.高可用
将多个Zuul节点注册到Eureka Server上
5.pre和post过滤器
前置pre:
@Component
public class TokenFilter extends ZuulFilter {
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return PRE_DECORATION_FILTER_ORDER-1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
String token = request.getParameter("token");
if (StringUtils.isEmpty(token)){
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
return null;
}
}
后置post
@Component
public class AddResponseHeaderFilter extends ZuulFilter {
@Override
public String filterType() {
return POST_TYPE;
}
@Override
public int filterOrder() {
return SEND_RESPONSE_FILTER_ORDER-1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletResponse response = currentContext.getResponse();
response.setHeader("X-FOO", UUID.randomUUID().toString());
return null;
}
}
6.限流
限流时机:请求被转发之前调用(令牌桶限流)
@Component
public class RateLimiterFilter extends ZuulFilter {
private static final RateLimiter RATELIMITER= RateLimiter.create(100);
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return SERVLET_DETECTION_FILTER_ORDER-1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
if (!RATELIMITER.tryAcquire()){
throw new RateLimiterException();
}
return null;
}
}
7.鉴权
@Component
public class AuthBuyerFilter extends ZuulFilter {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return PRE_DECORATION_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
if ("/order/order/create".equals(request.getRequestURI())) {
return true;
}
return false;
}
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
/**
* /order/create 只能买家访问
* /order/finish 只能买家访问
* /product/list 都可以访问
*/
Cookie cookie = CookieUtil.get(request, "openid");
if (cookie == null || StringUtils.isEmpty(cookie.getValue())) {
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
return null;
}
}
8.跨域(跨域资源共享)
1.被调用的类或方法上加@CorssOrigin注解
2.在Zuul里增加CorsFilter过滤器
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter(){
final UrlBasedCorsConfigurationSource source=new UrlBasedCorsConfigurationSource();
final CorsConfiguration config=new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOrigins(Arrays.asList("*"));
config.setAllowedHeaders(Arrays.asList("*"));
config.setAllowedMethods(Arrays.asList("*"));
config.setMaxAge(300l);
source.registerCorsConfiguration("/**",config);
return new CorsFilter(source);
}
}