Zuul路由网管简介及基本使用
简介
Zuul API路由网关服务简介
请看上图,这里的API 路由网关服务 由Zuul实现,主要就是对外提供服务接口的时候,
起到了请求的路由和过滤作用,也因此能够隐藏内部服务的接口细节,从来有利于保护系统的安全性;
路由配置
Zuul 路由配置
我们新建一个module microservice-zuul-3001
这里我们的zuul也注册到eureka服务里,端口3001;
我们修改下Hosts,专门为zuul搞个本地域名映射
hosts文件 加下:
1 127.0.0.1 zuul.yuan.com
完整pom.xml
1 23 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4 4.0.0 56 10com.yuan 7t226microservice 81.0-SNAPSHOT 9microservice-zuul-3001 11 1213 15 161.8 1417 50 5118 21org.springframework.boot 19spring-boot-starter-web 2022 26org.springframework.boot 23spring-boot-starter-test 24test 2527 30 31org.springframework.cloud 28spring-cloud-starter-eureka 2932 35 36org.springframework.boot 33spring-boot-starter-actuator 3437 40org.springframework.cloud 38spring-cloud-starter-hystrix 3941 44 45org.springframework.cloud 42spring-cloud-starter-config 4346 49org.springframework.cloud 47spring-cloud-starter-zuul 4852 5953 5854 57org.springframework.boot 55spring-boot-maven-plugin 56
添加application.yml 配置
1 server: 2 port: 3001 3 context-path: / 4 spring: 5 application: 6 name: microservice-zuul 7 eureka: 8 instance: 9 instance-id: microservice-zuul:3001 10 prefer-ip-address: true 11 client: 12 service-url: 13 defaultZone: http://eureka2001.yuan.com:2001/eureka/,http://eureka2002.yuan.com:2002/eureka/,http://eureka2003.yuan.com:2003/eureka/ 14 info: 15 groupId: com.yuan.testSpringcloud 16 artifactId: microservice-zuul-3001 17 version: 1.0-SNAPSHOT 18 userName: http://yuan.com 19 phone: 123456
启动类:ZuulApplication_3001
加下@EnableZuulProxy注解
1 package com.yuan.microservicezuul3001; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 6 import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; 7 import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 8 9 @SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class}) 10 @EnableZuulProxy 11 public class MicroserviceZuul3001Application { 12 13 public static void main(String[] args) { 14 SpringApplication.run(MicroserviceZuul3001Application.class, args); 15 } 16 17 }
测试下:
启动三个eureka 然后再启动下一个1001服务,以及 zuul网关服务;
这里有两个服务;
我们直接请求:http://localhost:81/student/list 能获取到数据;
我们用 http://zuul.yuan.com:3001/microservice-student/student/list 域名+端口+服务名称+请求地址 也能请求到数据;
说明我们的路由基本配置OK
一:
二:
http://zuul.yuan.com:3001/microservice-student/student/hystrix访问如果出现错误,
解决方案:
内部服务Hystrix与feign的整合失效,不能走快速回退的方法,雪崩现象再现
1 server: 2 port: 3001 3 context-path: / 4 spring: 5 application: 6 name: microservice-zuul 7 eureka: 8 instance: 9 instance-id: microservice-zuul:3001 10 prefer-ip-address: true 11 client: 12 service-url: 13 defaultZone: http://eureka2001.yuan.com:2001/eureka/,http://eureka2002.yuan.com:2002/eureka/,http://eureka2003.yuan.com:2003/eureka/ 14 info: 15 groupId: com.yuan.testSpringcloud 16 artifactId: microservice-zuul-3001 17 version: 1.0-SNAPSHOT 18 userName: http://yuan.com 19 phone: 123456 20 21 zuul: 22 routes: 23 studentServer.serviceId: microservice-student 24 studentServer.path: /studentServer/** 25 ignored-services: "*" 26 prefix: /yuan 27 host: 28 socket-timeout-millis: 60000 29 connect-timeout-millis: 60000 30 31 feign: 32 hystrix: 33 enabled: true 34 35 hystrix: 36 command: 37 default: 38 execution: 39 timeout: 40 enabled: true 41 isolation: 42 thread: 43 timeoutInMilliseconds: 15000 44 ribbon: 45 ReadTimeout: 6000 46 ConnectTimeout: 6000 47 MaxAutoRetries: 0 48 MaxAutoRetriesNextServer: 1 49 eureka: 50 enabled: true
pom.xml
12 3 6com.yuan 4microservice-common 57 10org.springframework.boot 8spring-boot-starter-web 911 15org.springframework.boot 12spring-boot-starter-test 13test 1416 19 20 21org.springframework.cloud 17spring-cloud-starter-eureka 1822 25 26org.springframework.boot 23spring-boot-starter-actuator 2427 30org.springframework.cloud 28spring-cloud-starter-hystrix 2931 34 35org.springframework.cloud 32spring-cloud-starter-config 3336 39 40 41org.springframework.cloud 37spring-cloud-starter-zuul 3842 45org.springframework.cloud 43spring-cloud-starter-eureka 4446 49org.springframework.cloud 47spring-cloud-starter-ribbon 4850 53 54 55org.springframework.cloud 51spring-cloud-starter-config 5256 59org.springframework.cloud 57spring-cloud-starter-feign 58
方案二(推荐):
Zuul作为服务网关为了保证自己不被服务拖垮,本身已经集成了Hystrix对路由转发进行隔离。 为了方便开发人员对服务短路进行自定义处理,
ZuulFallbackProvider :Zuul 提供了 ZuulFallbackProvider 接口,开发人员可以通过实现该接口来完成自定义Hystrix Fallback
FallbackProvider :Spring Cloud Zuul 提供了 FallbackProvider替代了ZuulFallbackProvider接口。
1 package com.yuan.microservicezuul3001.fallback; 2 3 import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; 4 import org.springframework.http.HttpHeaders; 5 import org.springframework.http.HttpStatus; 6 import org.springframework.http.MediaType; 7 import org.springframework.http.client.ClientHttpResponse; 8 import org.springframework.stereotype.Component; 9 10 import java.io.ByteArrayInputStream; 11 import java.io.IOException; 12 import java.io.InputStream; 13 14 @Component 15 public class ZuulFallBack implements ZuulFallbackProvider { 16 17 @Override 18 public String getRoute() { 19 return "*"; 20 } 21 22 /** 23 * 在给zuul整合回退功能时,只要类实现ZuulFallbackProvider接口,并且注册bean即可。 24 * 25 * 不过需要注意的时,这个回退只有服务掉线或者超时的情况下才会触发(Camden.SR4版本测试是这样), 26 * 如果服务程序出现异常,此回退程序是不能处理的,异常会直接返回给调用者,比如页面。 27 * 28 * @return 29 */ 30 @Override 31 public ClientHttpResponse fallbackResponse() { 32 return new ClientHttpResponse() { 33 @Override 34 public HttpHeaders getHeaders() { 35 HttpHeaders headers = new HttpHeaders(); 36 headers.setContentType(MediaType.APPLICATION_JSON_UTF8);//application/json;charset=UTF-8 37 return headers; 38 } 39 40 @Override 41 public InputStream getBody() throws IOException { 42 String msg = "服务繁忙,请稍后....."; 43 //new ByteArrayInputStream("{\"code\":-1,\"msg\":\"服务暂不可用\"}".getBytes(StandardCharsets.UTF_8)) 44 return new ByteArrayInputStream(msg.getBytes()); 45 } 46 47 @Override 48 public String getStatusText() throws IOException { 49 return HttpStatus.BAD_REQUEST.getReasonPhrase();//400 50 } 51 52 @Override 53 public HttpStatus getStatusCode() throws IOException { 54 return HttpStatus.BAD_REQUEST; 55 } 56 57 @Override 58 public int getRawStatusCode() throws IOException { 59 return HttpStatus.BAD_REQUEST.value();//"Bad Request" 60 } 61 62 @Override 63 public void close() { 64 65 } 66 }; 67 } 68 }
Zuul路由映射配置
上面是zuul的简单使用,从接口地址很轻易的就暴露了服务提供者的唯一标识名microservice-student;有安全风险,我们需要将其隐藏;
ignored-services的作用是将原来的服务提供者唯一标识名禁用;
Prefix的作用是给服务加前缀
yml文件中添加以下配置:
1 zuul: 2 routes: 3 studentServer.serviceId: microservice-student 4 studentServer.path: /studentServer/** 5 ignored-services: "*" 6 prefix: /yuan
配置完毕后可通过以下链接做测试
http://zuul.javaxl.com:3001/microservice-student/student/list
http://zuul.javaxl.com:3001/studentServer/student/list
http://zuul.javaxl.com:3001/javaxl/microservice-student/student/list
http://zuul.javaxl.com:3001/javaxl/studentServer/student/list
对应的配置会出现上面的错误页面,这是正常现象。
成功页面
Zuul请求过滤配置
比如我们登录某个系统 需要身份验证,用户名密码啥的;
我们请求服务,也可以来设置身份验证,也就是过滤非法请求;Zuul通过ZuulFilter过滤器实现;
一般具体实现的话 每次经过Zuul服务网关 我们都对带来的token进行有效性验证;
我们先定义一个 AccessFilter类:
1 package com.yuan.microservicezuul3001.filter; 2 3 import com.netflix.zuul.ZuulFilter; 4 import com.netflix.zuul.context.RequestContext; 5 import com.netflix.zuul.exception.ZuulException; 6 import org.apache.log4j.Logger; 7 8 import javax.servlet.http.HttpServletRequest; 9 10 public class AccessFilter extends ZuulFilter { 11 12 Logger logger=Logger.getLogger(AccessFilter.class); 13 14 /** 15 * 判断该过滤器是否要被执行 16 */ 17 @Override 18 public boolean shouldFilter() { 19 return true; 20 } 21 22 /** 23 * 过滤器的具体执行逻辑 24 */ 25 @Override 26 public Object run() throws ZuulException { 27 RequestContext ctx = RequestContext.getCurrentContext(); 28 HttpServletRequest request = ctx.getRequest(); 29 String parameter = request.getParameter("accessToken"); 30 logger.info(request.getRequestURL().toString()+" 请求访问"); 31 if(parameter==null){ 32 logger.error("accessToken为空!"); 33 ctx.setSendZuulResponse(false); 34 ctx.setResponseStatusCode(401); 35 ctx.setResponseBody("{\"result\":\"accessToken is empty!\"}"); 36 return null; 37 } 38 // token判断逻辑 39 logger.info(request.getRequestURL().toString()+" 请求成功"); 40 return null; 41 } 42 43 /** 44 * 过滤器的类型 这里用pre,代表会再请求被路由之前执行 45 */ 46 @Override 47 public String filterType() { 48 return "pre"; 49 } 50 51 /** 52 * 过滤器的执行顺序 53 */ 54 @Override 55 public int filterOrder() { 56 return 0; 57 } 58 59 }
然后再开启下 Filter配置:
1 package com.yuan.microservicezuul3001.config; 2 3 import com.yuan.microservicezuul3001.filter.AccessFilter; 4 import org.springframework.context.annotation.Bean; 5 import org.springframework.context.annotation.Configuration; 6 7 @Configuration 8 public class ZuulConfig { 9 10 @Bean 11 public AccessFilter accessFilter(){ 12 return new AccessFilter(); 13 } 14 }
浏览器输入地址进行测试
http://zuul.javaxl.com:3001/javaxl/studentServer/student/list
http://zuul.javaxl.com:3001/javaxl/studentServer/student/list?accessToken=1
测试结果如下