入门案例:创建Zuul项目,添加springboot-web启动器依赖,以及eureka-client的依赖,添加Zuul的依赖,还有springcloud
在配置文件中修改端口号和服务名称,指定eureka注册中心的地址,在启动类上添加Zuul代理的注解@EnableZuulProxy,启动服务。
启动之前的一个服务,不使用代理的情况下直接访问:
使用Zuul进行网关代理:网关服务的地址+要代理的服务名称+访问URI
Zuul的配置路由规则:url、serviceId
通过查看源码可以看到一些属性的默认值,对一些属性进行配置。
配置网关过滤器:在Zuul项目中新建一个类,放在启动类的子包中
测试:
package com.tangfen.filter;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
@Component
public class ZuulFilter extends com.netflix.zuul.ZuulFilter{
public static final Logger logger = LoggerFactory.getLogger(ZuulFilter.class);
/**
* 过滤内容
*/
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
logger.info("filter--->method={},url={}", request.getMethod(),request.getRequestURL().toString());
return null;
}
/**
* 是否开启过滤器,默认不开启
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 过滤顺序
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 过滤类型
*/
@Override
public String filterType() {
return "pre";
}
}
启动测试:
过滤器类型:
Zuul请求的生命周期:
模拟权限验证:拷贝上一个项目,修改服务名和项目名,
在过滤器中加入模拟验证的方法
启动访问,token为空:
token不为空:
filter的执行顺序:值越小,执行越早
复制一份过滤器的类
将过滤顺序的返回值修改为1,在过滤内容中输出一句话
启动测试:
过滤器的执行顺序需要指定为同类型,即过滤类型为同一类型才可指定执行顺序
异常处理:当发生异常时走error,新建post和error的过滤器以及异常处理的类
将过滤器的过滤类型分别修改为post和error,修改后执行的pre过滤器,手动抛出一个异常
启动测试:
Zuul和Hystrix结合,Zuul中依赖了Hystrix,所以直接使用就行
使用zuul访问provider,然后使用dashboard监控zuul
服务降级:
package com.tangfen;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
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;
/**
* 对 Provider-Product 服务降级处理
*
* @author Administrator
*
*/
@Component
public class ProductProviderFallback implements FallbackProvider {
/**
* 当服务无法执行时,该方法返回托底信息
*/
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return new ClientHttpResponse() {
/**
* 设置响应的头信息
*/
@Override
public HttpHeaders getHeaders() {
HttpHeaders header = new HttpHeaders();
MediaType mt = new MediaType("application", "json", Charset.forName("utf-8"));
header.setContentType(mt);
return header;
}
/**
* 设置响应体
*/
@Override
public InputStream getBody() throws IOException {
String content = "商品服务不可用,请与管理员联系";
return new ByteArrayInputStream(content.getBytes());
}
/**
* ClientHttpResponse 的 fallback 的状态码 返回 String
*/
@Override
public String getStatusText() throws IOException {
return this.getStatusCode().getReasonPhrase();
}
/**
* ClientHttpResponse 的 fallback 的状态码 返回 HttpStatus
*/
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
}
/**
* ClientHttpResponse 的 fallback 的状态码 返回 int
*/
@Override
public int getRawStatusCode() throws IOException {
return this.getStatusCode().value();
}
@Override
public void close() {
// TODO Auto-generated method stub
}
};
}
/**
* 给定对哪个服务做降级处理
*/
@Override
public String getRoute() {
return "ebook-product-provider";
}
}
Zuul服务限流:添加依赖:
##全局配置限流
#zuul.ratelimit.enabled=true
###60s 内请求超过 3 次,服务端就抛出异常,60s 后可以恢复正常请求
#zuul.ratelimit.default-policy.limit=3
#zuul.ratelimit.default-policy.refresh-interval=60
###针对 IP 进行限流,不影响其他 IP
#zuul.ratelimit.default-policy.type=origin
局部限流和全局限流配置基本类似,不过在default-policy后加入要限流的服务名称即可。
网关限流参数
Zuul性能调优:设置Hystrix和ribbon的超时时间
配置文件
Spring Cloud Config:
创建配置中心服务端:新建项目,添加config-server的坐标
修改启动类,
在配置文件中添加Git的url
新建配置文件,上传到Git中,通过url访问配置文件
在Git中新建仓库:
配置文件的命名规则与访问:
新建客户端,添加依赖
修改启动类
修改配置文件,和server关联起来:
首先把名称修改为bootstrap.yml或者bootstrap.properties
配置中心原理图:
在Git仓库中修改配置如何让服务不重启生效:配置发生修改时,当有服务访问config-server时会同步到server端的本地仓库中,但是client不重启的话并不会重新读取到最新的配置。
1、在client端加Actuator依赖,用来refresh项目,
2、开启刷新,默认为true
3、刷新时使用的是post方式,而且由于spring创建对象使用的是单例模式,所以需要重新创建一个对象,这就需要用到@RefreshScope注解,这个注解的作用是刷新作用域。
4、发送post请求时使用httpclient工具类,修改发送请求的地址即可,当client和server都在运行时,修改了远程仓库的配置文件,只需要使用该工具类发送post请求即可。