目录
启用网关
负载均衡
路由端点
配置指定微服务的访问路径
忽略微服务
前缀
灰度发布功能
敏感Header
接口容错
限流
过来的url改造成别的url
Zuul的自带Route过滤器使用
actuator查看路由和过滤器
Pre过滤器控制不通过Route过滤器
启用网关
新建项目引入依赖
org.springframework.cloud spring-cloud-starter-netflix-eureka-clientorg.springframework.cloud spring-cloud-starter-netflix-zuul
配置文件
eureka.client.service-url.defaultZone=http://euk1.com:7001/eureka/ spring.application.name=zuulserver server.port=80
启动类
@EnableZuulProxy
测试访问
网关会将服务名转换成具体服务的ip和端口,实际进行访问
http://localhost/consumer/alive
负载均衡
启动两个Consumer
轮询访问上面地址,会看到返回结果中,端口一直轮询在变。说明负载均衡生效了,默认是轮询
consumer.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
路由端点
调试的时候,看网关请求的地址,以及 映射是否正确。网关请求有误时,可以通过此处排查错误。
配置
management.endpoints.web.exposure.include=* management.endpoint.health.show-details=always management.endpoint.health.enabled=true management.endpoint.routes.enabled=true
配置指定微服务的访问路径
1. 通过服务名配置(虚拟主机名)
zuul.routes.consumer=/xxoo @Component public class GrayFilter extends ZuulFilter { @Override public String filterType() { return FilterConstants.ROUTE_TYPE; } @Override public int filterOrder() { return 0; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { RequestContext currentContent = RequestContext.getCurrentContext(); HttpServletRequest request = currentContent.getRequest(); String userId = request.getHeader("userId"); //根据用户Id查规则 if("1".equals(userId)){ RibbonFilterContextHolder.getCurrentContext().add("version","v2"); }else{ RibbonFilterContextHolder.getCurrentContext().add("version","v1"); } return null; } }
敏感Header
这个主要是设置cookie里哪些值会被传到后面!!
测试点:
停止一个api-driver。访问:yapi:网关token,看返回。
初始请求。返回值中token为msb cookie
加上下面配置
敏感的header不会传播到下游去,也就是说此处的token不会传播的其它的微服务中去。
zuul: #一下配置,表示忽略下面的值向微服务传播,以下配置为空表示:所有请求头都透传到后面微服务。 sensitive-headers: token
访问。网关token为null。
接口容错
@Component
public class MsbFallback implements FallbackProvider{
@Override
public String getRoute() {
// TODO Auto-generated method stub
return "*";
}
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
if (cause instanceof HystrixTimeoutException) {
return response(HttpStatus.GATEWAY_TIMEOUT);
} else {
return response(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
private ClientHttpResponse response(final HttpStatus status) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
//return status;
return HttpStatus.BAD_REQUEST;
}
@Override
public int getRawStatusCode() throws IOException {
//return status.value();
return HttpStatus.BAD_REQUEST.value();
}
@Override
public String getStatusText() throws IOException {
//return status.getReasonPhrase();
//return HttpStatus.BAD_REQUEST.name();
return HttpStatus.BAD_REQUEST.getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
String msg = "{"msg":"服务故障"}";
return new ByteArrayInputStream(msg.getBytes());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}
选用基础yml
测试点:启动eureka,api-driver, online-taxi-zuul
正常启动,正常访问yapi 网关token。正常
停止api-driver。
则走了容错 方法。
将fallback的改成:
@Override
public String getRoute() {
// TODO Auto-generated method stub
// return "*";
return "api-passenger";
}
在访问上面 yapi 中 zuul,中网关token。则报500。
再改成:
@Override
public String getRoute() {
// TODO Auto-generated method stub
// return "*";
// return "api-passenger";
return "api-driver";
}
重写访问,熔断生效。
最后改回去*。
限流
保护自己,用ratelimit。
令牌桶
假设进入高速公路的车辆需要在入口处领取到通行卡才能进入高速公路。为了节约人力成本,入口处放置自动出卡机。按照国家高速公路交通安全法的规定,在高速公路上行驶的车辆,车速超过100km/h时,应与同车道前车保持100米以上距离。为了保持最小安全行车距离100米,按车速100km/h计算,需要间隔至少3.6秒才能放行一辆车,因此出卡机每隔3.6秒出一张通行卡。在自动出卡机下放置一个盒子,自动出卡机按照3.6秒的间隔向盒子中投放通行卡。每辆进入高速公路的车辆,从盒子中领取通行卡之后才可以进入高速公路。
令牌桶可以看作是一个存放一定数量令牌的容器。系统按设定的速度向桶中放置令牌。当桶中令牌满时,多出的令牌溢出,桶中令牌不再增加。在使用令牌桶对流量规格进行评估时,是以令牌桶中的令牌数量是否足够满足报文的转发为依据的。每个需要被转发的报文,都要从令牌桶中领取一定数量的令牌(具体数量视报文大小而定),才可以被正常转发。如果桶中存在足够的令牌可以用来转发报文,称流量遵守或符合约定值,否则称为不符合或超标。
1. 启动jmeter,双击:jmeter.bat
2. 右击TestPlan,add ,Threads,Thread Group
3. 右击测试令牌桶线程组,add,sampler, http request。
4. 在线程组:
1、Number of Threads(users):用户个数
2、Ramp-up Period(in seconds):在多长时间内,加载指定的用户个数,单位为s。假如需加载100个用户,在5s中之内加载完成,那么平均每秒钟加载20个用户。
3、Loop Count(循环次数):用户执行操作的循环次数,如果选择forever,则永远循环下去。
测试点:启动eureka,api-driver,online-taxi-zuul。
令牌桶设置成2,jemter 用10个并发。可以看到控制台输出结果。
过来的url改造成别的url
例如老项目中,原来的url,微服务改造后变成别的url了,通过网关进行转发
例如
app : /url/xxx/xxx将url中的test31转成服务提供的test3
方法1
zuul.
route.
随便写自定义名
path:=/account/**
serviceId=account
/account/a
没有/a
问题:原来的url不动1,而服务没有提供相应的接口
这个方法实际上是修改服务名,而不是修改对应的具体接口
方法2:
使用灰度的方式,使用filter进行转发
方法3:
使用nginx进行转发
方法4:
使用Zuul的自定义route过滤器进行转发
1.过滤器,route。
2.获取 请求过来的url(请求)
3. url (请求)= url (目的地)映射。
4. 设置RequestContext 中的 serviceld , url
开发之前,想清楚步骤。
技术和业务做选择和取舍。
@Component
public class CommonServicePathFilter extends ZuulFilter {
private final static String GETWAY_FOWARD_PREFIX="getway_forward_";
private final static String GETWAY_COMPAY_CONFIG_KEY = "getway_company";
@Autowired
private RedisTemplate redisTemplate;
@Override
public String filterType() {
//这里很重要,必须是route
return "route";
}
@Override
public int filterOrder() {
return 1;
}
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
String url = ctx.getRequest().getRequestURI();
Map forwardMap = getForwardMap(url);
if(forwardMap != null){
String fowardUrl = forwardMap.get(url);
String serviceId = getServiceId(fowardUrl);
String requestUrl = getRequestUrl(fowardUrl,serviceId);
//1.设置目标service的Controller的路径
ctx.put(FilterConstants.REQUEST_URI_KEY,requestUrl);
//2.设置目标service的serviceId
ctx.put(FilterConstants.SERVICE_ID_KEY,serviceId);
}
return null;
}
private String getServiceId(String url){
if(url.startsWith("/")){
String temp = url.substring(1);
return temp.split("/")[0];
}else{
return null;
}
}
private String getRequestUrl(String url,String serviceId){
return url.substring(serviceId.length() +1);
}
@Override
public boolean shouldFilter() {
return true;
}
private Map getForwardMap(String originalUrl){
//todo:这里是返回一个map,传入一个originUrl,返回一个要转发的url
}
}
Zuul的自带Route过滤器使用
路由过滤器
RibbonXXXFilter :将url 路由到服务
SimpleHostRoutingFilter :将url路由到 url 地址
SendForwardFilter : 转发(转向zuul自己)
RibbonRoutingFilter order 10
将url路由到服务
zuul: routes: quality: /请求路径/**
其中 quality 为服务的名称
SimpleHostRoutingFilter order 100
将url路由到url地址
yml 配置:
zuul:
routes:
#自己转发到自己 名字任意起
xxx: 如果找不到会报404的错误(类似于将让eureka找到自己的服务,这个是zuul里面的)
path: /前端请求的地址/**
url: http://…… 接口的地址(全路径)
SendForwardFilter order 500
将url路由到自己的controller
yml 配置:
zuul:
routes:
#自己转发到自己 名字任意起
xxx:
path: /前端请求的地址/**
url: forward:/接口的地址
例如
访问 localhost:9090/forword1/
设置
实际上访问zuul的
actuator查看路由和过滤器
路由规则的查看。http://localhost:9100/actuator/routes
pom:yml: management: endpoints: web: exposure: include: "*" endpoint: health: ##默认是never show-details: ALWAYS enabled: true routes: enabled: true org.springframework.boot spring-boot-starter-actuator
过滤器的查看: http://localhost:9100/actuator/filters
Pre过滤器控制不通过Route过滤器
ip过滤。次数限制,设备号过滤。
pre过滤器中设置。sendzuulresponse (false ),只控制不向 route过滤器 执行(即其他的pre还是执行的)
因为ribbonroutefilter的shouldFilter判断了sendZuulResponse条件。



