声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅。html
一、概念:Zuul 路由访问java
二、具体内容web
在如今为止全部的微服务都是经过 Eureka 找到的,可是在不少的开发之中为了规范微服务的使用,提供有一个路由的处理控制组件:Zuul,也就是说 Zuul 就做为中间的一个代理层出现。spring
本次使用 Zuul 将访问无安全认证的微服务信息,例如:公司信息就属于无安全认证的微服务;安全
一、 为了突出 zuul 的功能,创建一个新的主机映射:服务器
127.0.0.1 gateway-9501.com
之后全部的微服务的访问再也不直接进行处理了,而是经过 Zuul 进行跳转后得到app
二、 创建一个新的模块:microcloud-zuul-gateway-9501;负载均衡
三、 【microcloud-zuul-gateway-9501】修改 pom.xml 文件,追加 zuul 相关依赖包:ide
· 注意:Zuul 服务最终仍是会注册到 Eureka 之中,那么千万要将其配置好;spring-boot
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency>
四、 【microcloud-zuul-gateway-9501】修改 application.yml 配置文件:
server:
port: 9501
eureka:
client: # 客户端进行Eureka注册的配置
service-url:
defaultZone: http://edmin:studyjava@eureka-7001.com:7001/eureka,http://edmin:studyjava@eureka-7002.com:7002/eureka,http://edmin:studyjava@eureka-7003.com:7003/eureka
instance:
lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
lease-expiration-duration-in-seconds: 5 # 若是如今超过了5秒的间隔(默认是90秒)
instance-id: gateway-9501.com # 在信息列表时显示主机名称
prefer-ip-address: true # 访问的路径变为IP地址
info:
app.name: study-microcloud
company.name: www.study.cn
build.artifactId: $project.artifactId$
build.version: $project.verson$
spring:
application:
name: microcloud-zuul-gateway
五、 【microcloud-zuul-gateway-9501】建立程序启动的主类:
package cn.study.microcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @SpringBootApplication @EnableZuulProxy public class Zuul_9501_StartSpringCloudApplication { public static void main(String[] args) { SpringApplication.run(Zuul_9501_StartSpringCloudApplication.class, args); } }
能够看到【microcloud-zuul-gateway-9501】已经注册到eureka中了
六、 访问公司微服务信息:
· 原始访问路径:http://company-8101.com:8101/company/get/hello;
· Zuul 代理访问:http://gateway-9501.com:9501/microcloud-provider-company/company/get/hello;
如今使用 Zuul 代理的只有 company,由于 dept 上有安全认证不能访问。
总体的 Zuul 运行以后你会发现,zuul 所实现就是一个代理功能,那么如今就会出现一个问题,例如:以以前访问的路径为例:
http://gateway-9501.com:9501/microcloud-provider-company/company/get/hello
此时必需要知道应用程序的名称,可是若是不知道这个名称确定没法访问,但是若是让用户知道这个名称,那么使用 zuul 就 没有任何的实际意义,直接调用便可。而 zuul 的主要功能是代理,那么代理的功能就是不让用户看见真实的操做,因此在实际的使用之中就须要为 zuul 设置一些路由规则。
一、 【microcloud-zuul-gateway-9501】为指定的应用设置路径,修改 application.yml 配置文件:
zuul: routes: microcloud-provider-company: /company-proxy/**
那么此时就能够经过“/company-proxy”来访问“microcloud-provider-company”名称。
http://gateway-9501.com:9501/company-proxy/company/get/hello
可是如今还会存在有一个实际的问题,虽然如今开启了路由访问支持,可是依然支持经过应用名称进行访问:
http://gateway-9501.com:9501/microcloud-provider-company/company/get/hello
二、 【microcloud-zuul-gateway-9501】修改 application.yml 配置文件忽略掉应用名称访问:
· 忽略掉“microcloud-provider-company”应用名称;
zuul: ignored-services: microcloud-provider-company routes: microcloud-provider-company: /company-proxy/**
这个时候就能够进行代理的安全使用,可是若是你一个系统之中存在有几百个微服务,若是按照如上的方式进行配置就会非 常的麻烦,因此最简单的作法是能够采用一个通配符“*”的模式来完成:
zuul: ignored-services: "*" routes: microcloud-provider-company: /company-proxy/**
如今表示全部的 Eureka 中的服务名称的信息访问都要忽略掉,全部的访问都须要配置一个映射路径的模式来完成。
三、 【microcloud-zuul-gateway-9501】除了以上的模式进行服务定义以外,在 zuul 之中也能够采用以下的方式进行处理:
zuul: ignored-services: "*" routes: mycompany.path: /company-proxy/** mycompany.serviceId: microcloud-provider-company
其中在代码里面出现的“mycompany”是一个逻辑名称,该名称的主要做用是将 path 与 serviceId 绑定在一块儿。
四、 【microcloud-zuul-gateway-9501】若是说如今不想经过 Eureka 进行访问,则也能够直接链接到 company 微服务的地址
zuul: ignored-services: "*" routes: company.path: /company-proxy/** company.url: http://company-8101.com:8101/company
此时的地址上因为已经存在有了“company”前缀,因此访问地址为:
http://gateway-9501.com:9501/company-proxy/get/hello
可是从实际的开发来说不建议采用此类模式处理,由于全部的服务若是直接绑定了指定的服务提供者的地址,那么将不方便 进行负载均衡的配置处理,并且没有 Eureka 全部微服务的管理也很是不方便。
五、 【microcloud-zuul-gateway-9501】设置公共前缀:
zuul: prefix: /study-proxy ignored-services: "*" routes: microcloud-provider-company: /company-proxy/**
一旦存在有前缀定义以后全部微服务的访问上就必须追加有前缀名称:
http://gateway-9501.com:9501/study-proxy/company-proxy/company/get/hello
以上的地址:
· “/study-proxy”:整个 zuul 的前缀;
· “/company-proxy”:是在 zuul 中定义的映射路径;
· “/company/get/hello”:是微服务提供者提供的操做路径。
对于 zuul 的功能本质上就属于一个代理操做,可是在实际的使用之中,全部的微服务必定都要有本身的认证信息,那么在这 样的状态下,若是你当前所代理的微服务具备认证信息,那么就必须在其访问前追加认证的头部操做,这样的功能就须要经过 zuul的过滤操做完成。
一、 【microcloud-zuul-gateway-9501】修改 application.yml 配置,这个配置之中追加 dept 微服务的代理;
zuul: prefix: /study-proxy ignored-services: "*" routes: microcloud-provider-company: /company-proxy/** microcloud-provider-dept: /dept-proxy/**
此时的访问路径:http://studyjava:hello@gateway-9501.com:9501/study-proxy/dept-proxy/dept/get/1;如今的密码只是设置给了 zuul,而 zuul 并不可以将认证的信息传递到部门微服务之中。
二、 【microcloud-zuul-gateway-9501】追加过滤处理操做:
package cn.study.microcloud.filter; import java.nio.charset.Charset; import java.util.Base64; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; public class AuthorizedRequestFilter extends ZuulFilter { // 进行受权访问处理 @Override public Object run() { // 表示具体的过滤执行操做 RequestContext currentContext = RequestContext.getCurrentContext() ; // 获取当前请求的上下文 String auth = "studyjava:hello"; // 认证的原始信息 byte[] encodedAuth = Base64.getEncoder() .encode(auth.getBytes(Charset.forName("US-ASCII"))); // 进行一个加密的处理 // 在进行受权的头信息内容配置的时候加密的信息必定要与“Basic”之间有一个空格 String authHeader = "Basic " + new String(encodedAuth); currentContext.addZuulRequestHeader("Authorization", authHeader); return null; } @Override public boolean shouldFilter() { // 该Filter是否要执行 return true ; } @Override public int filterOrder() { return 0; // 设置优先级,数字越大优先级越低 } @Override public String filterType() { // 在进行Zuul过滤的时候能够设置其过滤执行的位置,那么此时有以下几种类型: // 一、pre:在请求发出以前执行过滤,若是要进行访问,确定在请求前设置头信息 // 二、route:在进行路由请求的时候被调用; // 三、post:在路由以后发送请求信息的时候被调用; // 四、error:出现错误以后进行调用 return "pre"; } }
三、 【microcloud-zuul-gateway-9501】创建一个配置程序类做为认证请求的配置 Bean。
package cn.study.microcloud.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import cn.study.microcloud.filter.AuthorizedRequestFilter; @Configuration public class ZuulConfig { @Bean public AuthorizedRequestFilter getAuthorizedRequestFilter() { return new AuthorizedRequestFilter() ; } }
那么这个时候就意味着你如今的程序能够直接利用 zuul 的代理访问全部加密的微服务。
四、 【microcloud-zuul-gateway-9501】考虑到 zuul 也须要进行安全访问,因此应该修改项目中的 pom.xml 配置文件,追加 Spring 安全访 问配置处理操做:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
五、 【microcloud-zuul-gateway-9501】修改 application.yml 配置文件,最佳有用户信息配置:
security:
basic:
enabled: true
user:
name: zdmin
password: studyjava
那么此时如今表示 zuul 的代理上有了认证信息,则访问的地址上必须加上 zuul 的认证操做:
http://zdmin:studyjava@gateway-9501.com:9501/study-proxy/dept-proxy/dept/get/1
六、 【microcloud-service】如今全部的服务要经过 zuul 的代理来进行操做对于代理的配置若是要经过 feign 进行访问,那么在编写 feign 的时候就必须设置代理的服务名称;
package cn.study.service; import java.util.List; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import cn.study.commons.config.FeignClientConfig; import cn.study.service.fallback.IDeptClientServiceFallbackFactory; import cn.study.vo.Dept; @FeignClient(value = "MICROCLOUD-ZUUL-GATEWAY", configuration = FeignClientConfig.class, fallbackFactory = IDeptClientServiceFallbackFactory.class) public interface IDeptClientService { @RequestMapping(method = RequestMethod.GET, value = "/study-proxy/dept-proxy/dept/get/{id}") public Dept get(@PathVariable("id") long id); @RequestMapping(method = RequestMethod.GET, value = "/study-proxy/dept-proxy/dept/list") public List<Dept> list(); @RequestMapping(method = RequestMethod.POST, value = "/study-proxy/dept-proxy/dept/add") public boolean add(Dept dept); }
七、 【microcloud-service】修改服务的配置类,测试访问的应该是 zuul 的地址:
package cn.study.commons.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import feign.Logger; import feign.auth.BasicAuthRequestInterceptor; @Configuration public class FeignClientConfig { @Bean public Logger.Level getFeignLoggerLevel() { return feign.Logger.Level.FULL ; } @Bean public BasicAuthRequestInterceptor getBasicAuthRequestInterceptor() { return new BasicAuthRequestInterceptor("zdmin", "studyjava"); } }
八、 【microcloud-zuul-gateway-9501】默认状况下只要配置了过滤器,就能够进行一个正常的启动,若是如今有些过滤器忽然不想让它 用了,则也能够经过修改 application.yml 配置文件让其禁用:
zuul: AuthorizedRequestFilter: pre: disable: true
此时表示“AuthorizedRequestFilter”过滤器将被禁止使用。若是之后有多个过滤服务出现的话,能够经过配置文件实现过滤 的启用与禁用控制。
Zuul 是一个代理服务,那么若是被代理的服务忽然断掉了,那么这个时候 zuul 上面必定会显示出错误信息。例如:如今中止 掉“dept-8001:8001”端口上的微服务。
若是如今程序没法使用,则 zuul 的代理执行时就会出现有 timeout 的信息。可是千万要记住,因为如今的客户端已经提供有了 feign 中的服务降级的配置支持,因此客户端没有任何的问题,问题只出如今代理端。可是对于一个完善的 zuul 的代理应该更好的 实现服务降级的处理操做,因此若是有须要也能够在 zuul 中进行服务降级配置。
一、 【microcloud-zuul-gateway-9501】创建一个 Fallback 的回退处理类。
package cn.study.microcloud.fallback; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.client.ClientHttpResponse; import org.springframework.stereotype.Component; @Component public class DeptProviderFallback implements ZuulFallbackProvider { @Override public String getRoute() { return "microcloud-provider-dept"; // 设置好处理的失败路由 } @Override public ClientHttpResponse fallbackResponse() { return new ClientHttpResponse() { @Override public InputStream getBody() throws IOException { return new ByteArrayInputStream( "{\"deptno\":777777,\"dname\":\"【ERROR】Zuul-Fallback\",\"loc\":\"Gateway客户端提供\"}" .getBytes()); // 当出现服务调用错误以后返回的数据内容 } @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders() ; headers.set("Content-Type", "text/html; charset=UTF-8"); return headers; } @Override public HttpStatus getStatusCode() throws IOException { return HttpStatus.BAD_REQUEST; } @Override public int getRawStatusCode() throws IOException { return HttpStatus.BAD_REQUEST.value(); } @Override public String getStatusText() throws IOException { return HttpStatus.BAD_REQUEST.getReasonPhrase(); } @Override public void close() { }}; } }
二、 【microcloud-zuul-gateway-9501】直接访问地址:
http://zdmin:studyjava@gateway-9501.com:9501/study-proxy/dept-proxy/dept/get/1
因为此时你返回的都是错误的代码,则客户端接收到此代码以后会认为服务器端已经死掉了。