1. zuul
功能:请求的路由和过滤
场景:请求校验等
2. zuul实现路由
使用:
加入依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
yml文件
server:
port: 9000
eureka:
client:
serviceUrl:
defaultZone: http://localhost:3000/eureka/ #eureka服务端提供的注册地址 参考服务端配置的这个路径
instance:
instance-id: zuul-0 #此实例注册到eureka服务端的唯一的实例ID
prefer-ip-address: true #是否显示IP地址
leaseRenewalIntervalInSeconds: 10 #eureka客户需要多长时间发送心跳给eureka服务器,表明它仍然活着,默认为30 秒 (与下面配置的单位都是秒)
leaseExpirationDurationInSeconds: 30 #Eureka服务器在接收到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除,默认为90秒
spring:
application:
name: zuul #此实例注册到eureka服务端的name
启动项和以往一样
@SpringBootApplication
@EnableZuulProxy
public class AppZuul {
public static void main(String[] args) {
SpringApplication.run(AppZuul.class);
}
}
跑起来
测试一波
开始进入正题了
目的:不能通过服务名访问服务
方法:
在yml中加入
zuul:
ignored-services: server-power
routes:
power:
serviceId: server-power
path: /power/**
power是自己定义的名字
/**代表所有层级
ignored-services不给通过这个服务名调用,ignored-services: '*'
禁止所有服务通过服务名调用
测试:
zuul:
prefix: /api
加入前缀
如果路径为@RequestMapping("/api/getPower.do")可以选择不清楚api前缀,需要加入以下配置
zuul:
prefix: /api
strip-prefix: false
经过路由后的路径将会带上前缀api
3. 过滤器
种类:PRE(请求被路由之前调用), ROUTING(将请求路由到微服务), POST(路由到微服务以后执行), ERROR(其他阶段发生错误时)
禁用默认过滤器:zuul.LogFilter.pre.disable=true(yml中设置)
使用方法:需要继承ZuulFilter类 实现其中方法
请求对象怎么来?
//过滤器的具体逻辑
//请求对象怎么来?
@Override
public Object run() throws ZuulException {
//RequestContext.getCurrentContext()得到一个threadLocal<? extends RequestContext>
RequestContext ctx = RequestContext.getCurrentContext();
...
return null;
}
小点:ThreadLocal(自己了解)
@Component
public class LogFilter extends ZuulFilter {
//过滤器类型
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
//优先级
@Override
public int filterOrder() {
return 0;
}
//判断该过滤器是否要执行
@Override
public boolean shouldFilter() {
return true;
}
//过滤器的具体逻辑
//请求对象怎么来?
@Override
public Object run() throws ZuulException {
//RequestContext.getCurrentContext()得到一个threadLocal<? extends RequestContext>
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
System.out.println(request.getRemoteAddr()+"访问了"+request.getRequestURI());
return null;
}
}
访问http://localhost:9000/api/power/getPower.do会在控制台显示
0:0:0:0:0:0:0:1访问了/api/power/getPower.do
4. zuul容错和回退
zuul默认是整合了hystrix和ribbon的,要使用hystrix需要实现FallbackProvider 类重写里面的方法
package com.lulu.provider;
import com.netflix.hystrix.exception.HystrixTimeoutException;
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 java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
@Component
public class FallBackProvider implements FallbackProvider {
@Override
public String getRoute() {
//制定为哪个微服务提供回退(这里写微服务名 写*代表所有微服务)
return "*";
}
//此方法需要返回一个ClientHttpResponse对象 ClientHttpResponse是一个接口,具体的回退逻辑要实现此接口
//route:出错的微服务名 cause:出错的异常对象
@Override
public ClientHttpResponse fallbackResponse(String route, final Throwable cause) {
//这里可以判断根据不同的异常来做不同的处理, 也可以不判断
//完了之后调用response方法并根据异常类型传入HttpStatus
if (cause instanceof HystrixTimeoutException) {
return response(HttpStatus.GATEWAY_TIMEOUT);
} else {
return response(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
private ClientHttpResponse response(final HttpStatus status) {
//这里返回一个ClientHttpResponse对象 并实现其中的方法,关于回退逻辑的详细,便在下面的方法中
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
//返回一个HttpStatus对象 这个对象是个枚举对象, 里面包含了一个status code 和reasonPhrase信息
return status;
}
@Override
public int getRawStatusCode() throws IOException {
//返回status的code 比如 404,500等
return status.value();
}
@Override
public String getStatusText() throws IOException {
//返回一个HttpStatus对象的reasonPhrase信息
return status.getReasonPhrase();
}
@Override
public void close() {
//close的时候调用的方法, 讲白了就是当降级信息全部响应完了之后调用的方法
}
@Override
public InputStream getBody() throws IOException {
//吧降级信息响应回前端
return new ByteArrayInputStream("降级信息".getBytes());
}
@Override
public HttpHeaders getHeaders() {
//需要对响应报头设置的话可以在此设置
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}
停掉power测试
5. zuul集群
1. 思想
yml配置
zuul
server:
port: 9000
eureka:
client:
serviceUrl:
defaultZone: http://localhost:3000/eureka/ #eureka服务端提供的注册地址 参考服务端配置的这个路径
instance:
instance-id: zuul-0 #此实例注册到eureka服务端的唯一的实例ID
prefer-ip-address: true #是否显示IP地址
leaseRenewalIntervalInSeconds: 10 #eureka客户需要多长时间发送心跳给eureka服务器,表明它仍然活着,默认为30 秒 (与下面配置的单位都是秒)
leaseExpirationDurationInSeconds: 30 #Eureka服务器在接收到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除,默认为90秒
spring:
application:
name: zuul #此实例注册到eureka服务端的name
zuul:
ignored-services: "*"
routes:
power:
serviceId: zuul-server
path: /zuul/**
prefix: /api
# strip-prefix: false
# order:
# serviceId: server-order
# path: /order/**
zuul9001
server:
port: 9001
eureka:
client:
serviceUrl:
defaultZone: http://localhost:3000/eureka/ #eureka服务端提供的注册地址 参考服务端配置的这个路径
instance:
instance-id: zuul-server-1 #此实例注册到eureka服务端的唯一的实例ID
prefer-ip-address: true #是否显示IP地址
leaseRenewalIntervalInSeconds: 10 #eureka客户需要多长时间发送心跳给eureka服务器,表明它仍然活着,默认为30 秒 (与下面配置的单位都是秒)
leaseExpirationDurationInSeconds: 30 #Eureka服务器在接收到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除,默认为90秒
spring:
application:
name: zuul-server #此实例注册到eureka服务端的name
zuul:
ignored-services: "*"
routes:
power:
serviceId: server-power
path: /power/**
# prefix: /api
# order:
# serviceId: server-order
# path: /order/**
zuul9002
server:
port: 9002
eureka:
client:
serviceUrl:
defaultZone: http://localhost:3000/eureka/ #eureka服务端提供的注册地址 参考服务端配置的这个路径
instance:
instance-id: zuul-server-2 #此实例注册到eureka服务端的唯一的实例ID
prefer-ip-address: true #是否显示IP地址
leaseRenewalIntervalInSeconds: 10 #eureka客户需要多长时间发送心跳给eureka服务器,表明它仍然活着,默认为30 秒 (与下面配置的单位都是秒)
leaseExpirationDurationInSeconds: 30 #Eureka服务器在接收到实例的最后一次发出的心跳后,需要等待多久才可以将此实例删除,默认为90秒
spring:
application:
name: zuul-server #此实例注册到eureka服务端的name
zuul:
ignored-services: "*"
routes:
power:
serviceId: server-power
path: /power/**
# prefix: /api
# strip-prefix: false
# order:
# serviceId: server-order
# path: /order/**
启动eureka3000,zuul,zuul9001,zuul9002,power