本章节回顾下前段时间负责搭建网关所涉及的内容:由于网关特殊性,功能简单但要求并不低;功能方面不复杂只要:流量转发,鉴权,熔断,监控;运维方面:,高并发,高可用,简化配置,不能过多要求配置增加运维成本,因此综合考虑值得用一篇文章坐下记录,便于后期有bug或回溯能快速拾起来。

                                                        zuul实践

一:路由:初始化配置,规则加载,路由缓存,请求拦截并寻址

1:路由规则:初始化读取配置

 1。初始化对url路径的预处理

 2。处事初始化zuulFilter拦截器(非本次重点)init提一下是有这个内容

 3。初始化httpclinet 这里后面服务通信再讲,init提一下是有这个内容

2:规则加载

 3:路由缓存

 4:请求拦截并寻址

二:负载均衡:默认集成ribbon负载均衡和其七种算法策略,

三:服务通信:服务通信及调用原理 

1:DiscoverClient源码:

2:  DiscoveryClientRouteLocator属性和拥有几个重要的能力

四:熔断机制:hystix熔断回滚配置

 2:补充:

Zuul网关过滤器生命周期


系统功能:

1:配置中心采用CC,公司架构组结合开源增强自研,类似nacos配置中心,disconf的功能,实现nacos自动刷新功能(不是本文重点,这里不做详解;有意可以去nacos官网学习

2:esg服务注册与发现与nacos注册中心两者皆兼容实现(in 和 out);这里esg类似开源ESB企业服务总线在SOA架构中实现服务间智能化集成与管理的中介(不是本文重点,这里不做详解;有意可以去这github;另外这老哥总结也不错link

3:网关zuul功能实现(重点,下面逐条)

  • 路由:初始化配置,规则加载,路由缓存,请求拦截并寻址
  • 负载均衡:默认集成ribbon负载均衡和其七种算法策略,
  • 服务通信:服务通信及调用原理
  • 熔断机制:hystix熔断回滚配置

前提概述
zuul作为Servlet的实现,对于一般情况,ZuulServet被嵌入到Spring Dispatch机制中,由DispatcherServlet分派处理,这样Spring MVC可以控制路由,并且Zuul缓冲请求。

请求转发由 SimpleHostRoutingFilter、RibbonRoutingFilter 完成,前者通过Apache HttpClient来转发请求,后者与Ribbon、Hystrix一起,完成客户端负载均衡及应用守护工作。

如果需要绕过multipart处理,在不缓冲请求的情况下通过Zuul(例如,对于大文件上传),ZuulServlet也可以装载在Spring Dispatcher之外,让请求绕过DispatcherServlet。默认情况下,ZuulServlet的mapping地址是/zuul。此路径可以使用zuul.servletPath更改。


一:路由:初始化配置,规则加载,路由缓存,请求拦截并寻址

1:路由规则:初始化读取配置

1。初始化对url路径的预处理

esa调用实现_ide

esa调用实现_ide_02

2。处事初始化zuulFilter拦截器(非本次重点)init提一下是有这个内容

请求转发由 SimpleHostRoutingFilter、RibbonRoutingFilter 完成,前者通过Apache HttpClient来转发请求,后者与Ribbon、Hystrix一起,完成客户端负载均衡及应用守护工作。
 

esa调用实现_esa调用实现_03

 3。初始化httpclinet 这里后面服务通信再讲,init提一下是有这个内容

esa调用实现_ide_04

2:规则加载

esa调用实现_ide_05

 3:路由缓存

esa调用实现_esa调用实现_06

 4:请求拦截并寻址

esa调用实现_ide_07

二:负载均衡:默认集成ribbon负载均衡和其七种算法策略,

RandomRule:随机算法实现  RoundRobinRule:轮询负载均衡策略,依次轮询所有可用服务器列表,遇到第一个可用的即返回   RetryRule :先按照RoundRobinRule策略获取服务,如果获取服务失败会在指定时间内重试   AvaliabilityFilteringRule: 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值)    BestAvailableRule :会先过滤掉由于多次访问故障二处于断路器跳闸状态的服务,然后选择一个并发量最小的服务   WeightedResponseTimeRule: 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低   ZoneAvoidanceRule: 复合判断server所在区域的性能和server的可用性选择server

三:服务通信:服务通信及调用原理 

1:DiscoverClient源码:

esa调用实现_esa调用实现_08

esa调用实现_初始化_09

esa调用实现_esa调用实现_10

2:  DiscoveryClientRouteLocator属性和拥有几个重要的能力

在将路由属性存入RequestContext后,上面我们提到url路径统一为requestURI属性,但是转发的目标分为3种属性,在filterType为route类型的zuulfilter对其实现最终的转发。
1.serviceId对应RibbonRoutingFilter类,order为10,委托RibbonCommand的execute方法进行转发。
2.routeHost对应SimpleHostRoutingFilter类,order为100,委托CloseableHttpClient的execute进行转发。
3.forward.to对应SendForwardFilter类,order为500,委托RequestDispatcher的forward方法进行转发。

        DiscoveryClientRouteLocator它基于DiscoveryClinet路由数据来自properties静态配置和从注册中心获取的数据

  1.   动态添加Route
  2.   刷新路由
  3.   从DiscoveryClient获取路由信息,但用途不大

四:熔断机制:hystix熔断回滚配置

在spring cloud中,Zuul启动器中包含了Hystrix相关依赖,在Zuul网关工程中,默认是提供了Hystrix Dashboard服务监控数据的(hystrix.stream),但是不会提供监控面板的界面展示。可以说,在spring cloud中,zuul和Hystrix是无缝结合的。

/**
 * 如果需要在Zuul网关服务中增加容错处理fallback,需要实现接口ZuulFallbackProvider
 * spring-cloud框架,在Edgware版本(包括)之后,声明接口ZuulFallbackProvider过期失效,
 * 提供了新的ZuulFallbackProvider的子接口 - FallbackProvider
 * 在老版本中提供的ZuulFallbackProvider中,定义了两个方法。
 *  - String getRoute()
 *    当前的fallback容错处理逻辑处理的是哪一个服务。可以使用通配符‘*’代表为全部的服务提供容错处理。
 *    如果只为某一个服务提供容错,返回对应服务的spring.application.name值。
 *  - ClientHttpResponse fallbackResponse()
 *    当服务发生错误的时候,如何容错。
 * 新版本中提供的FallbackProvider提供了新的方法。
 *  - ClientHttpResponse fallbackResponse(Throwable cause)
 *    如果使用新版本中定义的接口来做容错处理,容错处理逻辑,只运行子接口中定义的新方法。也就是有参方法。
 *    是为远程服务发生异常的时候,通过异常的类型来运行不同的容错逻辑。
 */
@Component
public class TestFallBbackProvider implements FallbackProvider {
 
    /**
     * return - 返回fallback处理哪一个服务。返回的是服务的名称
     * 推荐 - 为指定的服务定义特性化的fallback逻辑。
     * 推荐 - 提供一个处理所有服务的fallback逻辑。
     * 好处 - 服务某个服务发生超时,那么指定的fallback逻辑执行。如果有新服务上线,未提供fallback逻辑,有一个通用的。
     */
    @Override
    public String getRoute() {
        return "eureka-application-service";
    }
 
    /**
     * fallback逻辑。在早期版本中使用。
     * Edgware版本之后,ZuulFallbackProvider接口过期,提供了新的子接口FallbackProvider
     * 子接口中提供了方法ClientHttpResponse fallbackResponse(Throwable cause)。
     * 优先调用子接口新定义的fallback处理逻辑。
     */
    @Override
    public ClientHttpResponse fallbackResponse() {
        System.out.println("ClientHttpResponse fallbackResponse()");
        
        List<Map<String, Object>> result = new ArrayList<>();
        Map<String, Object> data = new HashMap<>();
        data.put("message", "服务正忙,请稍后重试");
        result.add(data);
        
        ObjectMapper mapper = new ObjectMapper();
        
        String msg = "";
        try {
            msg = mapper.writeValueAsString(result);
        } catch (JsonProcessingException e) {
            msg = "";
        }
        
        return this.executeFallback(HttpStatus.OK, msg, 
                "application", "json", "utf-8");
    }
 
    /**
     * fallback逻辑。优先调用。可以根据异常类型动态决定处理方式。
     */
    @Override
    public ClientHttpResponse fallbackResponse(Throwable cause) {
        System.out.println("ClientHttpResponse fallbackResponse(Throwable cause)");
        if(cause instanceof NullPointerException){
            
            List<Map<String, Object>> result = new ArrayList<>();
            Map<String, Object> data = new HashMap<>();
            data.put("message", "网关超时,请稍后重试");
            result.add(data);
            
            ObjectMapper mapper = new ObjectMapper();
            
            String msg = "";
            try {
                msg = mapper.writeValueAsString(result);
            } catch (JsonProcessingException e) {
                msg = "";
            }
            
            return this.executeFallback(HttpStatus.GATEWAY_TIMEOUT, 
                    msg, "application", "json", "utf-8");
        }else{
            return this.fallbackResponse();
        }
    }
    
    /**
     * 具体处理过程。
     * @param status 容错处理后的返回状态,如200正常GET请求结果,201正常POST请求结果,404资源找不到错误等。
     *  使用spring提供的枚举类型对象实现。HttpStatus
     * @param contentMsg 自定义的响应内容。就是反馈给客户端的数据。
     * @param mediaType 响应类型,是响应的主类型, 如:application、text、media。
     * @param subMediaType 响应类型,是响应的子类型, 如:json、stream、html、plain、jpeg、png等。
     * @param charsetName 响应结果的字符集。这里只传递字符集名称,如:utf-8、gbk、big5等。
     * @return ClientHttpResponse 就是响应的具体内容。
     *  相当于一个HttpServletResponse。
     */
    private final ClientHttpResponse executeFallback(final HttpStatus status, 
            String contentMsg, String mediaType, String subMediaType, String charsetName) {
        return new ClientHttpResponse() {
 
            /**
             * 设置响应的头信息
             */
            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders header = new HttpHeaders();
                MediaType mt = new MediaType(mediaType, subMediaType, Charset.forName(charsetName));
                header.setContentType(mt);
                return header;
            }
 
            /**
             * 设置响应体
             * zuul会将本方法返回的输入流数据读取,并通过HttpServletResponse的输出流输出到客户端。
             */
            @Override
            public InputStream getBody() throws IOException {
                String content = contentMsg;
                return new ByteArrayInputStream(content.getBytes());
            }
 
            /**
             * ClientHttpResponse的fallback的状态码 返回String
             */
            @Override
            public String getStatusText() throws IOException {
                return this.getStatusCode().getReasonPhrase();
            }
 
            /**
             * ClientHttpResponse的fallback的状态码 返回HttpStatus
             */
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return status;
            }
 
            /**
             * ClientHttpResponse的fallback的状态码 返回int
             */
            @Override
            public int getRawStatusCode() throws IOException {
                return this.getStatusCode().value();
            }
 
            /**
             * 回收资源方法
             * 用于回收当前fallback逻辑开启的资源对象的。
             * 不要关闭getBody方法返回的那个输入流对象。
             */
            @Override
            public void close() {
            }
        };
    }
}

 2:补充:

Zuul网关过滤器生命周期

esa调用实现_ide_11


做一个

说话有趣,稳着冷静,见识高明,眼神清澈的人