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);
}
}