ZUUL基础知识
zuul是spring cloud提供的一个通用api网关组件
ZUUl过滤器
1、4种类型
pre、routing、post、error
顺序:pre>routing>post
2、参数配置
注意:
/zuul 路径下网关会跳过dispatcherServlet 而由zuulServlet处理
3、实现服务降级
zuul包下是带hystrix包
#ribbonTimeout = (ReadTimeout + ConnectTimeout) * (maxAutoRetries + 1) * (maxAutoRetriesNextServer + 1);
ribbon:
ReadTimeout: 10000
ConnectTimeout: 10000
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 60000
实战环境
工具:IntelliJ IDEA 2019.2.4
JDK:1.8
父项目以及注册中心、服务方详见之前博客。
【消费方与之前服务方步骤一致,以下文章步骤基本一致】
步骤
1、打开父项目,file->new module
2、填写项目信息、next
3、pom文件新增连个依赖包
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
4、yml文件:
server:
port: 8000
spring:
application:
name: cloud-zuul
eureka:
client:
service-url:
defaultZone: http://user:123456@localhost:8080/eureka
healthcheck:
enabled: true #健康检查(需要spring-boot-starter-actuator依赖)
instance:
prefer-ip-address: true
lease-renewal-interval-in-seconds: 10 # 续约更新时间间隔(默认30秒)
lease-expiration-duration-in-seconds: 10 # 续约到期时间(默认90秒)
#zuul代理配置 zuul.routes.服务名.path,服务名要与注册的一致
zuul:
routes:
api-provider:
path: /api-provider/**
service-id: cloud-provider #应用名映射
api-consumer:
path: /api-consumer/**
service-id: cloud-consumer #应用名映射
ignored-patterns: /**/admin/** #过滤掉匹配URL
sensitive-headers: #默认会过滤 "Cookie", "Set-Cookie", "Authorization" 会影响统一授权
# strip-prefix: true #默认时或true时 转发到服务的请求是/**,如果stripPrefix=false,转发的请求是直接/api-consumer/**
# prefix: /api #会对所有的path增加一个/api前缀
5、application加入Zuul注解
@EnableZuulProxy
6.启动,查看注册中心
7、通过ZUUL调用
访问provider
http://localhost:8000/api-provider/sayHi
访问:consumer
http://localhost:8000/api-consumer/houseManage//queryCustomerInfoByTel?tel=232
8、新增权限校验AcessFiltler
访问:http://localhost:8000/api-consumer/houseManage/queryCustomerInfoByTel?tel=232&acessToken=123
package com.cloud.zuul.filter;
import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.http.HttpStatus;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* @author 10450
* @description 权限token校验
* @date 2022/9/2 14:45
*/
@Component
public class AcessFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return FilterConstants.PRE_DECORATION_FILTER_ORDER - 2;//最前进行校验
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
//1、获取request对象
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
//2、获取token参数
String token = request.getParameter("acessToken");
//3、对比token
if(token == null || !("123".equals(token))){//假设token查到为123
//4、token校验失败,直接响应数据
Map<String,Object> result = new HashMap<>();
result.put("code",HttpStatus.SC_UNAUTHORIZED);
result.put("msg","存在SQL注入风险");
ctx.getResponse().setContentType("text/html;charset=UTF-8");
ctx.setResponseBody(JSONObject.toJSONString(result));
ctx.setSendZuulResponse(false);//不响应
// ctx.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);//401
}
return null;
}
}
9、新增服务降级
package com.cloud.zuul.fallback;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @author 10450
* @description ZUUL实现降级
* @date 2022/9/2 14:36
*/
@Component
public class ZuulFallback implements FallbackProvider {
@Override
public String getRoute() {
return "*"; //指定全部出现问题的服务都走这个降级方法
}
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {//route表示服务名
System.out.println("降级的服务:"+route);
cause.printStackTrace();//问题打印
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
@Override
public int getRawStatusCode() throws IOException {
return HttpStatus.INTERNAL_SERVER_ERROR.value(); //500状态码
}
@Override
public String getStatusText() throws IOException {
//指定错误信息
return HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
String msg = "当前服务:"+ route + ",出现问题";
return new ByteArrayInputStream(msg.getBytes());
}
@Override
public HttpHeaders getHeaders() {
//指定响应头信息
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}