一、整合步骤
本文主要讲的是如何整合zuul网关,“基于SpringBoot整合SpringCloud微服务框架--Eureka注册中心及Feign远程调用/Ribbon负载均衡及Hystrix熔断器”请参考我的上一篇有关springcloud的博客:https://www.cnblogs.com/lkw-cnblogs/p/15764195.html,本文也是基于它的项目基础上作进一步的开发。
1、子模块springcloud_study_zuulserver目录结构
2、步骤
1 //子模块zuul网关服务创建及配置 2 1、基于maven创建zuul子模块 3 2、在pom.xml添加相关依赖 4 <parent> 5 <artifactId>springcloud_study</artifactId> 6 <groupId>org.lkw</groupId> 7 <version>1.0-SNAPSHOT</version> 8 </parent> 9 <modelVersion>4.0.0</modelVersion> 10 11 <artifactId>springcloud_study_zuulserver</artifactId> 12 13 <dependencies> 14 <dependency> 15 <groupId>org.springframework.cloud</groupId> 16 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 17 </dependency> 18 <dependency> 19 <groupId>org.springframework.boot</groupId> 20 <artifactId>spring-boot-starter-web</artifactId> 21 </dependency> 22 <!-- 引入Zuul网关框架依赖 --> 23 <dependency> 24 <groupId>org.springframework.cloud</groupId> 25 <artifactId>spring-cloud-starter-netflix-zuul</artifactId> 26 </dependency> 27 </dependencies> 28 3、在application.yml进行服务配置(此处只使用了zuul的动态路由功能,它还有安全验证等等功能) 29 # 服务调用者即消费者配置 30 server: 31 port: 8766 32 spring: 33 application: 34 # 该服务的名字 35 name: server-zuul 36 eureka: 37 client: 38 serviceUrl: 39 # eureka服务的地址 40 defaultZone: http://localhost:8761/eureka/ 41 # 配置zuul网关,实现动态路由 42 zuul: 43 routes: 44 feign: 45 path: /feign/** 46 serviceId: server-feign 47 ribbon: 48 path: /ribbon/** 49 serviceId: server-ribbon 50 4、创建zuul网关服务启动类 51 /* 52 *@author lkw 53 * zuul服务启动类 54 * 55 */ 56 @SpringBootApplication 57 @EnableEurekaClient 58 //在项目启动时加载zuul 59 @EnableZuulProxy 60 public class ZuulApplication { 61 62 public static void main(String[] args){ 63 SpringApplication.run(ZuulApplication.class,args); 64 } 65 } 66 5、分别创建不同的消费者的Fallback处理类(当zuul请求对应消费者服务时发生跳转错误时,可以通过该进行重定向或错误信息显示等处理) 67 /* 68 *@author lkw 69 * 由于网络原因或其它原因导致zuul跳转失败,因此我们需要去增加fallback类进行重定向,此处关联了server-feign服务 70 */ 71 @Component 72 public class WebFeignFallbackProvider implements FallbackProvider { 73 74 @Override 75 public String getRoute() { 76 return "server-feign"; //该fallback处理指向server-feign服务 77 } 78 79 /* 80 *请求服务失败,则返回指定的信息给调用者 81 */ 82 @Override 83 public ClientHttpResponse fallbackResponse(String route, Throwable cause) { 84 return new ClientHttpResponse() { 85 @Override 86 public HttpStatus getStatusCode() throws IOException { 87 return HttpStatus.OK; 88 } 89 90 @Override 91 public int getRawStatusCode() throws IOException { 92 return HttpStatus.OK.value(); 93 } 94 95 @Override 96 public String getStatusText() throws IOException { 97 return HttpStatus.OK.getReasonPhrase(); 98 } 99 100 @Override 101 public void close() { 102 103 } 104 105 @Override 106 public InputStream getBody() throws IOException { 107 ObjectMapper ob=new ObjectMapper(); 108 Map<String,Object> map=new HashMap<>(); 109 map.put("status",200); 110 map.put("message","网络异常,连接失败!"); 111 return new ByteArrayInputStream(ob.writeValueAsString(map).getBytes(StandardCharsets.UTF_8)); 112 } 113 114 @Override 115 public HttpHeaders getHeaders() { 116 HttpHeaders httpHeaders=new HttpHeaders(); 117 httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); 118 return httpHeaders; 119 } 120 }; 121 } 122 } 123 124 /* 125 *@author lkw 126 * 由于网络原因或其它原因导致zuul跳转失败,因此我们需要去增加fallback类进行重定向,此处关联了server-ribbon服务 127 */ 128 @Component 129 public class WebRibbonFallbackProvider implements FallbackProvider { 130 131 @Override 132 public String getRoute() { 133 return "server-ribbon"; //该fallback处理指向server-ribbon服务 134 } 135 136 /* 137 *请求服务失败,则返回指定的信息给调用者 138 */ 139 @Override 140 public ClientHttpResponse fallbackResponse(String route, Throwable cause) { 141 return new ClientHttpResponse() { 142 @Override 143 public HttpStatus getStatusCode() throws IOException { 144 return HttpStatus.OK; 145 } 146 147 @Override 148 public int getRawStatusCode() throws IOException { 149 return HttpStatus.OK.value(); 150 } 151 152 @Override 153 public String getStatusText() throws IOException { 154 return HttpStatus.OK.getReasonPhrase(); 155 } 156 157 @Override 158 public void close() { 159 160 } 161 162 @Override 163 public InputStream getBody() throws IOException { 164 ObjectMapper ob=new ObjectMapper(); 165 Map<String,Object> map=new HashMap<>(); 166 map.put("status",200); 167 map.put("message","网络异常,连接失败!"); 168 return new ByteArrayInputStream(ob.writeValueAsString(map).getBytes(StandardCharsets.UTF_8)); 169 } 170 171 @Override 172 public HttpHeaders getHeaders() { 173 HttpHeaders httpHeaders=new HttpHeaders(); 174 httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); 175 return httpHeaders; 176 } 177 }; 178 } 179 } 180 181 6、启动zuul项目,然后再分别启动之前的feign项目和ribbon项目 182 7、 183 (1)在浏览器里通过访问ip:zuul的服务端口/ribbon/ribbonHystrixHello,观察是否能通过zuul跳转到ribbon服务 184 (2)把ribbon服务关掉,重新访问/ribbon/ribbonHystrixHello,观察是否可以进行了fallback处理 185 8、 186 (1)同样地,在浏览器里通过访问ip:zuul的服务端口/feign/hello,观察是否能通过zuul跳转到feign服务 187 (2)把feign服务关掉,重新访问/feign/hello,观察是否可以进行了fallback处理
二、FAQ(问题集锦)
1、启动zuul项目时,“The bean 'proxyRequestHelper', defined in class path resource [org/springframework/cloud/netflix/zuul/ZuulProxyAutoConfiguration$NoActuatorConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/cloud/netflix/zuul/ZuulProxyAutoConfiguration$EndpointConfiguration.class] and overriding is disabled.”?
原因:springboot和springcloud版本不兼容
解决方法:保持spingboot版本2.1.x不变,更改springcloud版本为Greenwich.RELEASE,如下所示
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.17.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
</properties>
如果上面这个更改之后还是包下载有问题(可能是镜像站有ssl验证之类的),可以在maven设置里进行以下处理:
-Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true
2、进行zuul服务访问时,出现“com.netflix.zuul.exception.ZuulException: Forwarding error”错误?
原因:zuul服务的配置里的serviceID与实际的服务消费方名称不一致(此处原写为service-feign,实际应该为server-feign)
解决方法:
三、成果
1、在eureka注册中心,可以看到zuul服务已注册
2、通过zuul进行ribbon服务的跳转
3、通过zuul进行feign服务的跳转
4、当zuul跳转ribbon失败时,进行Fallback处理
5、当zuul跳转feign失败时,进行Fallback处理