SpringCloud principle of Zuul gateway and its configuration

  Zuul is spring cloud of micro-services gateway. Gateway: The gateway is the front entrance a whole network system. First request through the gateway routing path, to locate the particular service node.

  Zuul is a microblogging service gateway, the first is a micro service. It will also carry out registration and discovery services in Eureka registry. Is also a gateway, the request should be routed through Zuul.

  Zuul gateway is not necessary. Is recommended.

  Use Zuul, usually in the micro-services in larger quantities (more than 10), when recommended, management services have strict requirements when recommended, when the micro-service privileges demanding when recommended.

First, the role of the gateway Zuul

  Gateway has the following effects:

  • Unified entrance: Not all services provide a unique entry, gateway functions as an external and internal isolation, guarantee the safety of background services.
  • Authentication check: identifying each request authority, rejecting the request does not meet the requirements.
  • Dynamic Routing: dynamic route requests to different backend cluster.
  • Reduce the client and service side of the coupling: service can develop independently, do the mapping through the gateway layer.

    

Two, Zuul gateway applications

  1, the gateway access method

  By zuul access services, URL address of the default format: HTTP: // zuulHostIp: the URL of the service name port / want to access / service

  Service Name: properties profile spring.application.name.

  The service's URL: URL is the path to a service provided by the external monitor.

  2, the gateway dependency injection

<!-- spring cloud Eureka Client 启动器 -->
<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>
<! - Retry mechanism zuul gateway, instead of using the built-in ribbon retry mechanism
   Assembly is achieved by means of spring-retry retry
   Open zuul retry mechanism gateway needs to rely Addition
 -->
<dependency>
   <groupId>org.springframework.retry</groupId>
   <artifactId>spring-retry</artifactId>
</dependency>

  3, Gateway starter

/**
 * @EnableZuulProxy - open Zuul gateway.
 * The current application is a micro Zuul service gateway. The current service will be registered in Eureka registry. And find other services.
 * Need to rely on Zuul need is a spring-cloud-starter-zuul.
 */
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZuulApplication.class, args);
    }
}

  4, gateway global configuration variables

  4.1 URL path match

# URL pattern
# Match the routing rules using the trail.
# Key structure parameters: zuul.routes.customName.path = xxx
# Configure the path for the matching rules.
# Where customName custom. Typically use the service name to be called, to facilitate the subsequent management
# Wildcards can be used are: * **?
#? Single character
# * Any number of characters, does not include multi-level path
# ** any number of characters, include multi-level path
zuul.routes.eureka-application-service.path=/api/**
# Key configuration parameters: zuul.routes.customName.url = XXX
 # URL request for configuration matches the routing path of the service address. 
zuul.routes.eureka-application-service.url = http: //127.0.0.1: 8080 /

  4.2 service name match

# Service id pattern by routing service name
# key结构 : zuul.routes.customName.path=xxx
# Path matching rules
zuul.routes.eureka-application-service.path=/api/**
# Key structure: zuul.routes.customName.serviceId = XXX
 # request in accordance with the serviceId for configuring path routing path to the service name. 
zuul.routes.eureka-application-service.serviceId = eureka- application-service

  Service Name matching can also be used to simplify the configuration:

# Simple service id pattern simplify the configuration program
 # If the configuration only path, no configuration serviceId. CustomName equivalent to the service name. 
# Request in accordance with which the path routed directly to the corresponding service customName. 
zuul.routes.eureka-application-service.path = / api / **

  4.3 Routing Troubleshooting configuration

Service ignored the above mentioned id pattern #
 # Configure not list zuul management services. Multiple service names using a comma ',' separated. 
# Set the service will not be zuul agent.
zuul.ignored-services=eureka-application-service

# This mode is equivalent to all newly discovered exclude zuul default gateway access service mode, only the configuration of the routing gateway services can only be accessed by zuul gateway configuration exclusion list # a wildcard. zuul.ignored-services=* # Service name matching rules configured routing list, which is equivalent to only gateway proxy has been configured service. zuul.routes.eureka-application-service.path=/api/** # Configure a wildcard to exclude the gateway proxy path. All requests path in line ignored-patterns are not proxied zuul gateway. zuul.ignored-patterns=/**/test/** zuul.routes.eureka-application-service.path=/api/**

  4.4 prefix routing configuration

# Prefix URL pattern matching prefix route
 # Configure the request path prefix, this prefix is all based on a request by zuul gateway provides proxy.
zuul.prefix=/api
# Service name matching mode configuration request path rule.
# This configuration will be: http: // ip: port / api / appservice / ** request to provide zuul gateway proxy, can be accessed service prefix classification. 
# And the request is routed to the service eureka-application-service in. 
zuul.routes.eureka-application-service.path = / appservice / **

  5 Zuul gateway configuration summary

  There are a variety of gateway configuration, default, URL, service name, exclude | ignored, prefix .

  Gateway Configuration not good or bad quality, the appropriate configuration should be selected in different situations.

  zuul gateway using its underlying ribbon to achieve the requested routing, built MAMMALIA, and, selectively provides a gateway fallback logic. Use zuul when Feign is not recommended as a development to achieve application client side. After all, Feign technology is a repackaging of the ribbon using Feign itself will improve communication consumption, reducing communication efficiency , using Feign only when the service call each other to simplify code development is enough. And commercial development, a higher proportion Ribbon + RestTemplate to develop .

Three, Zuul gateway filters

  Zuul provided filter definition, the filter agent may be used to request additional functional logic. Such as: rights verification, logging and so on.

  Provided Zuul filter is a parent class. Parent is ZuulFilter . Abstract methods defined by the parent class filterType , to decide what kind of current Filter Yes. There prefilter, the route filtering, post-filtration, filtration abnormalities.

  • Prefilter : after the request to enter Zuul, filtering logic executed immediately.
  • After the route filtering : after the request to enter Zuul, and Zuul are used to filter routing logic execution of the request, the route filtering, is filtered before the remote service invocation logic.
  • Rear Filter : filtering logic executed after the remote service call.
  • Exception Filter : any time a filter is abnormal or inconclusive remote service invocation feedback filtering logic execution. No results back, is a remote service call timeout.

  Filter implementation 3.1

Inherit the parent class ZuulFilter. Providing four abstract method in the parent class, namely: filterType, filterOrder, shouldFilter, RUN . Its features are:

  • filterType: method returns the string data, representative of this type of filter. The possible values ​​are -pre, route, post, error.

pre - pre-filter, before performing the request is routed , typically for authentication processing, logging, and the like;

route - in the implementation of the route, before the service call is invoked;

error - any abnormal occurrence of a filter when executed or when the remote service invocation without feedback execution (time-out) , commonly used to treat abnormal;

post - in after the route or error calling , generally used to collect service information, statistics service performance indicators, can also do special handling of response results.

  • filterOrder: return int data, as for a plurality of filters with filterType custom execution order, the smaller the return value, the order of execution priority .
  • shouldFilter: return boolean data, representing the current filter is in effect .
  • run: specific filtering execution logic . The pre types of filters, can be verified by the request to determine whether to route the request to the service; post such types of filters can be done in response to the results of the service processing (e.g., increased footer data for each response).

  3.2 filter life cycle

            

  Code Example 3.3

/ ** 
 * Zuul filter must inherit ZuulFilter parent. 
 * The current object type must be handed over to the Spring container management. Use @Component notes describe. 
 * After inherited from the parent class, four abstract methods defined in the parent class must implement. 
 * ShouldFilter, RUN, filterType, filterOrder
  * /
@Component
public class LoggerFilter extends ZuulFilter {

    private static final Logger logger = LoggerFactory.getLogger(LoggerFilter.class);
    
    /**
     * 返回boolean类型。代表当前filter是否生效。
     * 默认值为false。
     * 返回true代表开启filter。
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * run方法就是过滤器的具体逻辑。
     * return 可以返回任意的对象,当前实现忽略。(spring-cloud-zuul官方解释)
     * 直接返回null即可。
     */
    @Override
    public Object run() throws ZuulException {
        // 通过zuul,获取请求上下文
        RequestContext rc = RequestContext.getCurrentContext();
        HttpServletRequest request = rc.getRequest();

        logger.info("LogFilter1.....method={},url={}",
                request.getMethod(),request.getRequestURL().toString());
        // 可以记录日志、鉴权,给维护人员记录提供定位协助、统计性能
        return null;
    }

    /**
     * 过滤器的类型。可选值有:
     * pre - 前置过滤
     * route - 路由后过滤
     * error - 异常过滤
     * post - 远程服务调用后过滤
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 同种类的过滤器的执行顺序。
     * 按照返回值的自然升序执行。
     */
    @Override
    public int filterOrder() {
        return 0;
    }
}

四、Zuul网关的容错(与Hystrix的无缝结合)

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

  4.1 Zuul中的服务降级处理

  在Edgware版本之前,Zuul提供了接口ZuulFallbackProvider用于实现fallback处理。从Edgware版本开始,Zuul提供了ZuulFallbackProvider的子接口FallbackProvider来提供fallback处理。
  Zuul的fallback容错处理逻辑,只针对timeout异常处理,当请求被Zuul路由后,只要服务有返回(包括异常),都不会触发Zuul的fallback容错逻辑。

  因为对于Zuul网关来说,做请求路由分发的时候,结果由远程服务运算的。那么远程服务反馈了异常信息,Zuul网关不会处理异常,因为无法确定这个错误是否是应用真实想要反馈给客户端的。

  4.2 代码示例

/**
 * 如果需要在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() {
            }
        };
    }
}

五、Zuul网关的限流保护

  Zuul网关组件也提供了限流保护。当请求并发达到阀值,自动触发限流保护,返回错误结果。只要提供error错误处理机制即可。

  Zuul的限流保护需要额外依赖spring-cloud-zuul-ratelimit组件。

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

  5.1 全局限流配置

  使用全局限流配置,zuul会对代理的所有服务提供限流保护。

# 开启限流保护
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

  5.2 局部限流配置

  使用局部限流配置,zuul仅针对配置的服务提供限流保护。

# 开启限流保护
zuul.ratelimit.enabled=true
# hystrix-application-client服务60s内请求超过3次,服务抛出异常。
zuul.ratelimit.policies.hystrix-application-client.limit=3
zuul.ratelimit.policies.hystrix-application-client.refresh-interval=60
# 针对IP限流。
zuul.ratelimit.policies.hystrix-application-client.type=origin

  5.3 限流参数简介

            

六、Zuul网关性能调优:网关的两层超时调优

  使用Zuul的spring cloud微服务结构图:

              

  从上图中可以看出。整体请求逻辑还是比较复杂的,在没有zuul网关的情况下,app client请求app service的时候,也有请求超时的可能。那么当增加了zuul网关的时候,请求超时的可能就更明显了。

  当请求通过zuul网关路由到服务,并等待服务返回响应,这个过程中zuul也有超时控制。zuul的底层使用的是Hystrix+ribbon来实现请求路由。结构如下:

                

  zuul中的Hystrix内部使用线程池隔离机制提供请求路由实现,其默认的超时时长为1000毫秒。ribbon底层默认超时时长为5000毫秒。如果Hystrix超时,直接返回超时异常。如果ribbon超时,同时Hystrix未超时,ribbon会自动进行服务集群轮询重试,直到Hystrix超时为止。如果Hystrix超时时长小于ribbon超时时长,ribbon不会进行服务集群轮询重试。

  那么在zuul中可配置的超时时长就有两个位置:Hystrix和ribbon。具体配置如下:

# 开启zuul网关重试
zuul.retryable=true
# hystrix超时时间设置
# 线程池隔离,默认超时时间1000ms
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=8000

# ribbon超时时间设置:建议设置比Hystrix小
# 请求连接的超时时间: 默认5000ms
ribbon.ConnectTimeout=5000
# 请求处理的超时时间: 默认5000ms
ribbon.ReadTimeout=5000
# 重试次数:MaxAutoRetries表示访问服务集群下原节点(同路径访问);MaxAutoRetriesNextServer表示访问服务集群下其余节点(换台服务器)
ribbon.MaxAutoRetries=1
ribbon.MaxAutoRetriesNextServer=1
# 开启重试
ribbon.OkToRetryOnAllOperations=true

  Spring-cloud中的zuul网关重试机制是使用spring-retry实现的。工程必须依赖下述资源:

<dependency>
  <groupId>org.springframework.retry</groupId>
  <artifactId>spring-retry</artifactId>
</dependency>

Guess you like

Origin www.cnblogs.com/jing99/p/11696192.html