Zuul 게이트웨이와 구성의 SpringCloud 원리

  Zuul 마이크로 서비스 게이트웨이의 스프링 구름이다. 게이트웨이 : 게이트웨이는 정문 전체적인 네트워크 시스템이다. 게이트웨이 라우팅 경로를 통해 먼저 요청, 특정 서비스 노드를 찾습니다.

  Zuul 가장 먼저 마이크로 서비스, 마이크로 블로깅 서비스 게이트웨이이다. 또한 유레카 레지스트리에 등록 및 검색 서비스를 수행합니다. 게이트웨이는 또한, 요청이 Zuul를 통해 라우팅해야한다.

  Zuul 게이트웨이가 필요하지 않습니다. 좋습니다.

  요구 마이크로 서비스 권한을 추천 할 때 때, 추천 할 때 일반적으로 권장하는 경우, 관리 서비스가 엄격한 요구 사항이 더 많은 양 (10 개 이상)의 마이크로 서비스에 Zuul를 사용합니다.

게이트웨이 Zuul의 첫 번째 역할

  Gateway는 다음과 같은 효과가 있습니다 :

  • 통합 입구 : 모든 서비스는 외부 및 내부 분리와 같은 고유 항목, 게이트웨이 기능을 제공하는 백그라운드 서비스의 안전을 보장합니다.
  • 인증 확인 : 요구 사항을 충족하지 않는 요청을 거부, 각 요청 권한을 식별.
  • 동적 라우팅 : 다른 백엔드 클러스터에 동적 요청을 라우팅.
  • 서비스는 독립적으로 발전 할 수있는 게이트웨이를 통해 계층의 매핑을 수행 결합의 클라이언트와 서비스 측면을 줄인다.

    

두, Zuul 게이트웨이 애플리케이션

  1 게이트웨이 액세스 방법

  : zuul 액세스 서비스, 기본 형식의 URL 주소로 HTTP : // zuulHostIp : 서비스 이름 포트의 URL이 / 액세스하려는 / 서비스

  서비스 이름 : 속성 spring.application.name 프로필.

  서비스의 URL : URL은 외부 모니터에서 제공하는 서비스에 대한 경로입니다.

  2 게이트웨이 의존성 삽입

<! - 봄 구름 유레카 클라이언트启动器-> 
< 의존성 > 
    < 의 groupId > org.springframework.cloud </ 의 groupId > 
    < artifactId를 > 스프링 클라우드 스타터 유레카 </ artifactId를 > 
</ 의존성 > 
< 의존성 > 
    < 의 groupId > org.springframework.cloud </ 의 groupId > 
    < artifactId를 > 스프링 클라우드 스타터 zuul </ artifactId를 > 
</ 의존성 >
<! -대신에 내장 된 재시도 메카니즘 리본을 사용 zuul 게이트웨이 재시도 메카니즘 
   어셈블리 구현 스프링 재시 재시 의해 
   zuul 재시도 메카니즘 게이트웨이 개구 첨가 의존해야 
 > - 
< 의존성 > 
   < 의 groupId > org.springframework.retry </ 의 groupId > 
   < artifactId를 > 스프링 재시 </ artifactId를 > 
</ 의존성 >

  3 게이트웨이 스타터

/ ** 
 * @EnableZuulProxy - 개방 Zuul 게이트웨이. 
 * 현재 응용 프로그램이 마이크로 Zuul 서비스 게이트웨이이다. 현재 서비스는 유레카 레지스트리에 등록됩니다. 그리고 다른 서비스를 찾을 수 있습니다. 
 Zuul 필요에 의존 할 필요 *은 스프링 클라우드 스타터 zuul입니다. 
 * / 
@SpringBootApplication @EnableZuulProxy

 공용  클래스 ZuulApplication {
     공공  정적  무효 메인 (문자열 []에 args) { 
        SpringApplication.run (ZuulApplication의. 클래스 , 인수); 
    } 
}

  4 글로벌 게이트웨이 구성 변수

  4.1 URL 경로가 일치

패턴 #의의 URL 
# 흔적를 사용하여 라우팅 규칙을 일치합니다. 
# 키 구성 매개 변수 : zuul.routes.customName.path = XXX 
# 일치하는 규칙에 대한 경로를 구성합니다. 
# 어디 customName 사용자 정의. 일반적으로의 후속 관리를 용이하게하기 위해, 호출 할 서비스 이름을 사용 
? 있습니다 사용할 수있는 와일드 카드 번호를 : * ** ? # 단일 문자 
# * 문자 사용, 다단계 경로를 포함하지 않습니다 
# ** 문자의 수는 다단계 경로를 포함
 
= service.path 파일의 응용 프로그램 zuul.routes.eureka / API / ** # 키 구성 매개 변수 : zuul.routes.customName.url = XXX
 # 구성 URL 요청은 서비스 주소의 라우팅 경로를 일치합니다. 
zuul.routes.eureka - 응용 프로그램 service.url = HTTP : //127.0.0.1 : 8080 /

  4.2 서비스 이름과 일치

서비스 이름 라우팅에 의해 # 서비스 ID 패턴 
zuul.routes.customName.path = XXX : # 키 구조를 
# 규칙과 일치하는 경로 
zuul.routes.eureka 파일의 응용 프로그램 service.path = / API / ** # 키 구조 : zuul.routes를. = XXX customName.serviceId의
 서비스 이름 경로 라우팅 경로를 구성하기위한 서비스 id 따른 # 요청. 
zuul.routes.eureka - 응용 프로그램 service.serviceId = eureka- 응용 프로그램 서비스

  서비스 이름 매칭도 구성을 단순화 할 수 있습니다 :

# 간단한 서비스 ID 패턴이 구성 프로그램의 단순화
 #을 만약 구성 전용 경로없이 구성 서비스 id. 서비스 이름에 해당 CustomName. 
경로가 해당 서비스 customName로 직접 라우팅되는 따른 # 요청. 
zuul.routes.eureka - 응용 프로그램 service.path = / API / **

  4.3 라우팅 문제 해결 구성

서비스는 위에서 언급 한 ID 패턴 #의 무시
 #이 zuul 관리 서비스를 나열하지 구성합니다. 쉼표를 사용하여 여러 서비스 이름 ','분리. 
# 서비스가 zuul 에이전트되지 않습니다 설정합니다. 
= 응용 프로그램 서비스의 유레카 - 서비스 - zuul.ignored 새로 zuul 기본 게이트웨이 액세스 서비스 모드를 제외 발견, 라우팅 게이트웨이 서비스의 구성 만 zuul 게이트웨이에 액세스 할 수 있습니다에이 모드는 동일합니다 #를 구성 제외 목록 # 와일드 카드. 
서비스 -zuul.ignored = * # 서비스 이름 매칭 규칙은 서비스 구성되어 전용 게이트웨이 프록시 동등 라우팅리스트를 구성. 
= service.path 파일의 응용 프로그램 zuul.routes.eureka / API / ** # 와일드 카드 게이트웨이 프록시 경로를 제외하는 배열. 라인 무시-패턴의 모든 요청 경로는 zuul 게이트웨이를 프록시되지 않습니다. 
패턴 = -zuul.ignored / ** / 테스트 / ** 
zuul.routes.eureka 파일의 응용 프로그램 service.path = / API / **

  4.4 접두사 라우팅 구성

# 접두어 URL 패턴 매칭 프리픽스 경로
 # 요청 경로 접두어 구성이 접두어 zuul 모든 게이트웨이에 의한 요청에 기초 프록시를 제공한다. 
= zuul.prefix / API의 # 규칙을 배치 한 서비스 이름 요청 경로와 일치합니다.
#이 구성됩니다 : HTTP : // IP : 포트 / API / appservice / ** zuul 게이트웨이 프록시를 제공하기 위해 요청, 액세스 할 수있는 서비스 접두어 분류. 
# 그리고 요청에 서비스 유레카 애플리케이션 서비스로 라우팅됩니다. 
zuul.routes.eureka - 응용 프로그램 service.path = / appservice / **

  5 Zuul 게이트웨이 구성 개요

  이 게이트웨이 구성, 다양한있는 기본, URL, 서비스 이름은 제외 | 무시 접두사 .

  게이트웨이 구성 좋은 또는 나쁜 품질하지, 적절한 구성이 다른 상황에서 선택해야합니다.

  zuul 게이트웨이 선택적 게이트웨이 대체 로직을 제공하고, 요청 라우팅 내장 포유류를 달성하기 위해 하부 리본을 이용하고. 척하기는 응용 프로그램의 클라이언트 측을 달성하기 위해 개발하지 않는 것이 좋습니다 때 zuul 사용합니다. 결국, 척하기 기술은 통신 효율을 감소, 통신 소비를 개선 척하기 자체를 사용하여 리본의 재 포장입니다 서로 코드 개발을 단순화 할 수있는 서비스 호출이 충분한 경우에만 척하기를 사용하여이. 그리고 상업 개발, 더 높은 비율 리본 + RestTemplate은 개발 .

세, Zuul 게이트웨이 필터

  Zuul 제공되는 필터 정의는 필터 에이전트를 추가 로직 기능을 요청하기 위해 사용될 수있다. 예를 들면 : 등등 권한 검증, 로깅 및.

  제공 Zuul 필터는 부모 클래스입니다. 부모는 ZuulFilter . 부모 클래스에 의해 정의 된 추상 메소드 filterType은 , 결정하는 현재의 필터의 종류 예. 경로 필터링, 후 여과, 여과 이상이,이 프리 필터.

  • 프리 필터 : 요청이 Zuul를 입력 한 후, 필터링 로직이 즉시 실행.
  • 경로 여과 후 : 요청 Zuul를 입력하고 Zuul 요청 라우트 필터링 라우팅 로직 실행을 필터링하는 데 사용 된 후, 원격 서비스 호출 로직 전에 필터링된다.
  • 후면 필터 : 원격 서비스 호출 후에 실행 필터링 논리.
  • 예외 필터 : 언제든지 필터 로직 실행 필터링 이상 또는 결정적 원격 서비스 호출 피드백이다. 다시 검색 결과가, 원격 서비스 호출 시간 제한이 없습니다.

  필터의 구현 3.1

부모 클래스 ZuulFilter을 상속합니다. 즉 부모 클래스에 네 추상적 인 방법을 제공 : filterType, filterOrder, shouldFilter, RUN을 . 그것의 기능은 다음과 같습니다

  • filterType는 : 방법은 문자열 데이터, 필터의 이러한 유형의 대표를 반환합니다. 가능한 값은 -pre, 경로, 게시, 오류가 있습니다.

사전 - 프리 필터, 상기 요청을 수행하는 라우팅되기 전에 , 통상의 인증 처리, 기록 등에 대한;

경로 -에서 서비스 호출하기 전에 경로의 구현은, 호출;

오류 - 필터의 비정상 발생을 실행하거나 할 때 피드백 실행 (타임 아웃)없이 원격 서비스 호출 일반적 이상 치료하기 위해 사용;

게시물 -에 경로 또는 오류 호출 한 후 , 일반적으로 서비스 정보, 통계 서비스 성과 지표를 수집하는 데 사용, 또한 응답 결과의 특수 처리를 할 수 있습니다.

  • filterOrder :로서는 리턴 int 데이터, filterType 맞춤 실행 순서로 복수의 필터, 작은 리턴 값, 실행 우선 순위 .
  • shouldFilter는 : 부울 데이터를 반환 현재 필터가 적용되는 표현 .
  • 실행 : 특정 필터링 실행 논리를 . (예를 들면, 각 응답 푸터 데이터를 증가) 필터 후 이러한 유형의 서비스의 처리 결과에 응답하여 수행 될 수 있으며, 필터의 사전 유형, 라우팅 서비스 요청할지 여부를 결정하기 위해 요청에 의해 검증 될 수있다.

  3.2 필터 수명주기

            

  코드 예제 3.3

/**
 * Zuul过滤器,必须继承ZuulFilter父类。
 * 当前类型的对象必须交由Spring容器管理。使用@Component注解描述。
 * 继承父类后,必须实现父类中定义的4个抽象方法。
 * 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>

추천

출처www.cnblogs.com/jing99/p/11696192.html