zuul网关_网关服务Zuul

一 什么是网关服务

1、为社么要使用网关服务

6aab8c20c1e1caaea61d30c6ee6f1a61.png

2 网关解决了什么问题

1e45cdfba6460ef2e544f84cfadb45fb.png

二 网关入门案例

1 创建项目,修改pom文件

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
	
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-zuul</artifactId>
		</dependency>

2 修改配置文件

spring.application.name=zuul-gateway
server.port=9010

#设置服务注册中心地址,指向另一个注册中心 
eureka.client.serviceUrl.defaultZone=http://eureka1:8080/eureka/,http://eureka2:9090/eureka/

3 修改启动类

/@SpringBootApplication
@EnableZuulProxy
public class ConsumerApplication {
	
	public static void main(String[] args) {
		SpringApplication.run(ConsumerApplication.class, args);
	}
}

4 访问服务测试

http://网关服务地址:网关服务端口/访问的服务的名称/访问的服务中的接口的地址

b984e9f544001d028ad314b7909e4071.png

三 Zuul路由规则

1 url指定路由规则

1.1 创建项目,修改pom文件

1.2 修改配置文件

spring.application.name=zuul-gateway
server.port=9010

#设置服务注册中心地址,指向另一个注册中心 
eureka.client.serviceUrl.defaultZone=http://eureka1:8080/eureka/,http://eureka2:9090/eureka/


# 1 ###################### 路由指定:URL 指定  ############################# 
# URL 匹配关键字,如果包含关键字就跳转到指定的 URL 中  
zuul.routes.e-book-product-provider.path=/ego-book-product-provider/**
zuul.routes.e-book-product-provider.url=http://127.0.0.1:9001/

1.3 修改启动类

1.4 通配符含义

39d03b24660ea34c996c1a942180b163.png

2 采用服务名称指定路由方式

## 2 ###################### 路由指定:服务指定 1  ############################# 
##将路径的/suibian/引到 eureka 的 e-book-product-provider 服务 上 
##规则:zuul.routes.路径名.path 
##规则:zuul.routes.路径名.serviceId=eureka 的服务名 
#zuul.routes.e-book-product-provider.path=/suibian/** 
#zuul.routes.e-book-product-provider.serviceId=e-book-product-provider 
 
 
## 3 ###################### 路由指定:服务指定 2   ############################# 
#zuul.routes 后面跟着的是服务名,服务名后面跟着的是路径规则,这种 配置方式更简单。
 zuul.routes 后面跟着的是服务名必须与provider的服务名一致
zuul.routes.e-book-product-provider.path=/suibian/** 

3 路由的排除方法

3.1 排除指定的某几个服务

## 4 ###################### 路由排除:排除某几个服务  #############################  ##排除后,这个地址将为空 http://127.0.0.1:9030/e-book-product-provider/product/findAll  
## 多个服务逗号隔开 
 #zuul.ignored-services=e-book-product-provider  

3.2 排除所有服务,在开放某几个服务

## 5 ###################### 路由排除:排除所有服务  ############################# 
#由于服务太多,不可能手工一个个加,故路由排除所有服务,然后针对要 路由的服务进行手工加 
#zuul.ignored-services=*
#zuul.routes.e-book-order-provider.path=/e-book-order-provi der/** 

3.3 排除关键字

## 6 ###################### 路由排除:排除指定关键字的路径  ############################# 
# 排除所有包括/list/的路径 
zuul.ignored-patterns=/**/findAll/**
zuul.routes.ego-book-order-provider.path=/suibian/**

4 路由的添加前缀的方法

访问服务的url必须加上前缀

## http://127.0.0.1:9030/suibian/product-provider/product/findAll 
zuul.prefix=/suibian
zuul.routes.e-book-product-provider.path=/product-provider/ ** 

四 网关过滤器

1 自定义网关过滤器

1 创建项目,添加zuul依赖

2 修改配置文件

3 修改启动类

/@SpringBootApplication
@EnableZuulProxy
public class ConsumerApplication {
	
	public static void main(String[] args) {
		SpringApplication.run(ConsumerApplication.class, args);
	}
}

4 编写拦截器

/@Component
public class LogFilter extends ZuulFilter{
	
	private static Logger logger = org.slf4j.LoggerFactory.getLogger(LogFilter.class);

	//是否开启拦截器,默认是false
	@Override
	public boolean shouldFilter() {
		// TODO Auto-generated method stub
		return true;
	}

	//过滤内容:在run方法编写过滤逻辑
	@Override
	public Object run() {
		
		//获取上下文对象
		RequestContext currentContext = RequestContext.getCurrentContext();
		HttpServletRequest request = currentContext.getRequest();
		logger.info("LogFilter......method={},url={}",request.getMethod(),request.getRequestURI().toString());
		return null;
	}

	//过滤器类型通过过滤器类型决定了过滤器执行的时间 
	@Override
	public String filterType() {
		// TODO Auto-generated method stub
		return "pre";
	}
	//过滤器的执行顺序:通过整数表示顺序,数值越小,优先级越高 
	@Override
	public int filterOrder() {
		// TODO Auto-generated method stub
		return 0;
	}

}

2 过滤器类型与生命周期

2.1 Zuul过滤器类型

b958b2e573dbc363f0e6ab5a19a97c3b.png

2.2 Zuul生命周期

a9c5ed228a910ecf0213f54b1d4d1f84.png

3 网关过滤器实现权限验证

需求:在网关过滤器中通过 Token 判断用户是否登录

3.1 创建项目,修改pom文件添加zuul坐标

3.2 修改配置文件

3.3 创建AccessFilter

/@Component
public class LogFilter extends ZuulFilter{
	
	private static Logger logger = org.slf4j.LoggerFactory.getLogger(LogFilter.class);
    
	//是否开启拦截器,默认是false
	@Override
	public boolean shouldFilter() {
		// TODO Auto-generated method stub
		return true;
	}

	//过滤内容:在run方法编写过滤逻辑
	@Override
	public Object run() {
		//获取上下文对象
		RequestContext cc = RequestContext.getCurrentContext();
		HttpServletRequest request = cc.getRequest();
		
		//从表单中获取token
		String token = request.getParameter("token");
		if(token == null) {
			logger.warn("tokne is null........");
			cc.setSendZuulResponse(true);//代表请求结束,不再继续向下执行
			cc.setResponseStatusCode(401);//设置响应状态吗
			cc.setResponseBody("{"result": "token is null...."}");//相应内容
			cc.getResponse().setContentType("text/html;charset=utf-8"); //响应类型 
		}else {
			//访问 redis 服务 进行验证    
			logger.info("token is OK"); 
		}
		
		return null;
	}

	//过滤器类型通过过滤器类型决定了过滤器执行的时间 
	@Override
	public String filterType() {
		// TODO Auto-generated method stub
		return "pre";
	}
	//过滤器的执行顺序:通过整数表示顺序,数值越小,优先级越高 
	@Override
	public int filterOrder() {
		// TODO Auto-generated method stub
		return 0;
	}

}

3.4 编写启动类

4 网关过滤器实现异常统一处理

1 创建ErrorFilter

/@Component
public class ErrorFilter extends ZuulFilter{
	
	private static Logger logger = org.slf4j.LoggerFactory.getLogger(ErrorFilter.class);
    
	//是否开启拦截器,默认是false
	@Override
	public boolean shouldFilter() {
		// TODO Auto-generated method stub
		return true;
	}

	//过滤内容:在run方法编写过滤逻辑
	@Override
	public Object run() {
		
			logger.info("-----------ErrorFilter----------------"); 
	
		return null;
	}

	//过滤器类型通过过滤器类型决定了过滤器执行的时间 
	@Override
	public String filterType() {
		// TODO Auto-generated method stub
		return "error";
	}
	//过滤器的执行顺序:通过整数表示顺序,数值越小,优先级越高 
	@Override
	public int filterOrder() {
		// TODO Auto-generated method stub
		return 0;
	}

2 执行顺序

d7615e242743123130638870f6b74a73.png

3 创建一场相应的过滤器

/@RestController
public class ExceptionHandler implements ErrorController {

	@Override
	public String getErrorPath() {
		
		return "/error";
	}

	@RequestMapping("/error")
	public String error() {
		return "{"error":"网络异常,请联系管理员,电话:120"}";
	}
}

五 网关容错

1 zuul 和 hystrix 无缝结合

在 zuul 的 jar 包中包含了 hystrix 的 jar 包。所以我们不需要在项目中添加 Hystrix 的坐标

1.1 访问网关服务的数据监控流

3a18b381ec0adfbf9a4d6b17c9aa3d7e.png

1.2 启动 dashboard-view 服务通过可视化界面查看监控数据

3f8dfd83e246f11ccab1b4c7c443a21b.png

2 在网关中实现对服务降级处理

如果需要对多个服务进行降级,需要编写多个类

2.1 创建项目,添加zuul依赖

2.2 修改配置文件

2.3 添加 ProviderProductFallback 类

/**
 * 对provider服务进行降级处理
 * @author 18722
 *
 */
@Component
public class ProductProviderFallback implements ZuulFallbackProvider{

	/**
	 * 给定对那个服务进行降级
	 */
	@Override
	public String getRoute() {
		// TODO Auto-generated method stub
		return "ego-book-product-provider";
	}
	
	/**
	 * 当服务无法执行时返回托底数据的方法
	 */
	@Override
	public ClientHttpResponse fallbackResponse() {

		ClientHttpResponse cr = new ClientHttpResponse() {
			
			//设置响应头信息
			@Override
			public HttpHeaders getHeaders() {
				HttpHeaders header = new HttpHeaders();
				MediaType mediaType = new MediaType("application","json",Charset.forName("utf-8"));
				header.setContentType(mediaType );
				return header;
			}
			//设置响应体信息
			@Override
			public InputStream getBody() throws IOException {
				String reponse = "商品服务不可用,请联系管理员,电话110";
				return new ByteArrayInputStream(reponse.getBytes());
			}
			
			// ClientHttpResponse 的 fallback 的状态码 返回 String 
			@Override
			public String getStatusText() throws IOException {
				// 调用getStatusCode将httpStatus转换为String
				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 {
				//调用getStatusCode将httpStatus转换为int
				return this.getStatusCode().value();
			}
			
			@Override
			public void close() {
				// TODO Auto-generated method stub
				
			}
		};
		return cr;
	}

六 网关限流实现自我保护

1 创建项目,修改pom'文件

<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-zuul</artifactId>
		</dependency>
		 <dependency>       
		 	<groupId>com.marcosbarbero.cloud</groupId>       
		 	<artifactId>spring-cloud-zuul-ratelimit</artifactId>       
		 	<version>1.3.4.RELEASE</version>   
		 </dependency> 

2 修改配置文件实现限流

2.1 全局限流

spring.application.name=zuul-gateway-ratelimit
server.port=9010

#设置服务注册中心地址,指向另一个注册中心 
eureka.client.serviceUrl.defaultZone=http://eureka1:8080/eureka/,http://eureka2:9090/eureka/


#全局配置限流 
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

测试 当当问第四下时,抛出异常

5fc3a9b792409db0667c3ae3b5e81e31.png

2.2 局部限流

# 局部限流:针对某个服务进行限流 
##开启限流 
#zuul.ratelimit.enabled=true
##60s 内请求超过 3 次,服务端就抛出异常,60s 后可以恢复正常请求 
#zuul.ratelimit.policies.ego-book-product-provider.limit=3
#zuul.ratelimit.policies.ego-book-product-provider.refresh-interval=60
##针对某个 IP 进行限流,不影响其他 IP
#zuul.ratelimit.policies.e-book-product-provider.type=origin

3 网关限流参数

33ba12cd8030df24c42c5ea9f5bb3750.png

七 Zuul两层性能调优

1 超时优化图解

Zuul底层采用了hystrix和ribbon来进行通信

当Zuul启动之后hystrix就有一个线程池,请求网关的线程都会进入到hystrix中,hystrix在根据网关中请求的路由规则的

处理,开启一个新的线程通过ribbon调用问我们的服务

** ribbon的超时时间要小于hystrix的超市时间,如果大于,当真正的有超时异常发生,不管ribbon调用有没有完成

hystrix之间返回超时异常,假如hystrix的超时时间为10,ribbon的超时时间为2,ribbon超时,但是hystrix

的线程没有超时,ribbon就会拿着这个线程接着请求集群中的其他节点,直到htstrix的线程池超时,这是才是真正的超时

a6830704e07a7515b512780cb85cb362.png

2 案例演示

2.1 创建项目,添加Zuul依赖

2.2 修改配置文件

spring.application.name=zuul-gateway-timeout
server.port=9010

#设置服务注册中心地址,指向另一个注册中心 
eureka.client.serviceUrl.defaultZone=http://eureka1:8080/eureka/,http://eureka2:9090/eureka/


#第一层 hystrix 超时时间设置 #默认情况下是线程池隔离,超时时间 1000ms 
hystrix.command.default.execution.isolation.thread.timeoutI nMilliseconds=8000
 
#第二层 ribbon 超时时间设置:设置比第一层小 # 请求连接的超时时间: 默认 5s
ribbon.ConnectTimeout=5000
# 请求处理的超时时间: 默认 5s 
ribbon.ReadTimeout=5000
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值