美文网首页JAVA基础(未看)
SpringCloud技术指南系列(十一)API网关之Zuul使

SpringCloud技术指南系列(十一)API网关之Zuul使

作者: 逍遥天扬 | 来源:发表于2019-10-11 10:51 被阅读0次

    SpringCloud技术指南系列(十一)API网关之Zuul使用

    一、概述

    API网关是一个更为智能的应用服务器,它的定义类似于面向对象设计模式中的Facade模式,它的存在就像是整个微服务架构系统的门面一样,所有的外部客户端访问都需要经过它来进行调度和过滤。它除了要实现请求路由、 负载均衡、 校验过滤等功能之外,还需要更多能力,比如与服务治理框架的结合、请求转发时的熔断机制、服务的聚合等一系列高级功能。

    在SpringCloud全家桶中,API网关有Zuul和gateway两种实现。

    1. zuul进来逐渐被gateway取代。
    2. zuul可以整合进任何SpringBoot应用
    3. gateway基于异步非阻塞模型,使用的netty+webflux实现,不能加入web依赖,默认加载加入webflux依赖。
    4. Spring Cloud zuul使用的仍是zuul 1.x,zuul 2.x也是异步非阻塞的。
    5. 选用zuul还是gateway,要看使用场景,如果在已有的非WebFlux项目使用,要用zuul。单纯的API网关独立部署,建议gateway。

    代码可以在SpringBoot组件化构建https://www.pomit.cn/java/spring/springcloud.html中的EurekaZuul、ZkZuul和ConsulZuul组件中查看,并下载。分别对应三种不同的服务注册方式。

    首发地址:
    品茗IT-同步发布

    如果大家正在寻找一个java的学习环境,或者在开发中遇到困难,可以加入我们的java学习圈,点击即可加入,共同学习,节约学习时间,减少很多在学习中遇到的难题。

    二、项目配置

    本篇的配置基于服务注册发现的项目基础上,并选择Consul + zuul为例讲解如何使用zuul做API网关。至于(Eureka + zuul)和 (zookeeper + zuul)写法上和(consul + zuul)是一样的,不再分开章节描述。

    这里选择Consul + zuul为例,是因为它在配置中有一个坑,其他两个倒是没有,下面配置时会着重说明下它。

    可以参考我前面的文章做对比:

    《SpringCloud技术指南系列(五)服务注册发现之Consul服务调用》

    《SpringCloud技术指南系列(三)服务注册发现之Eureka服务调用》

    《SpringCloud技术指南系列(七)服务注册发现之Zookeeper服务调用》

    2.1 引入依赖

    需要在建立好的项目中引入spring-cloud-starter-netflix-zuul.

    本篇是在consul的服务发现基础上进行zuul的配置,因此还需要引入consul相关配置。

    依赖如下:

    <?xml version="1.0"?>
    <project
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
        xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>cn.pomit</groupId>
            <artifactId>springcloudwork</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </parent>
        <artifactId>ConsulZuul</artifactId>
        <name>ConsulZuul</name>
        <url>http://maven.apache.org</url>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
            <maven-jar-plugin.version>2.6</maven-jar-plugin.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-consul-discovery</artifactId>
            </dependency>
            <!-- 使用feign时才用的上 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
            </dependency>
        </dependencies>
    </project>
    
    
    

    父模块pom文件可以在https://www.pomit.cn/spring/SpringCloudWork/pom.xml获取。

    2.2 配置文件

    这里使用yaml文件写配置,配置文件application.yml:

    application.yml:

    server:
       port: 8816
    spring:
       application:
          name: consulZuul
       cloud:
          consul:
             host: 127.0.0.1
             port: 8500
             discovery:
                prefer-ip-address: true
                healthCheckPath: /consulHeart/health
    zuul:
       ignoredServices: 
       routes:
          util:
             path: /util/**
             sensitiveHeaders: 
             serviceId: consulServer
          search:
             path: /search/**
             url: https://cn.bing.com/
    

    这里,表示API网关在8816端口监听,名字是consulZuul。

    • spring.cloud.consul开头的配置时consul服务注册发现的配置。前面章节已经有说明。
    • zuul.ignoredServices是要忽略的服务名称,这个地方有个坑,就是如果你在应用中有/consul这样的controller,它就会自动请求consul的8300端口,然后就导致失败,所以建议这个地址加个ignoredServices: consul
    • zuul.routes.util 这个表示,请求到/util这个路径时需要的处理,path是标明路径,sensitiveHeaders是标明传输的http头信息,serviceId是标明这个是consul上的服务,通过这个id找到对应的服务地址并转发。
    • zuul.routes.search 这个表示,请求到/search的配置,我这里是向外转发到必应做搜索。

    三、Zuul服务不可用降级

    Zuul默认整合了hystrix做熔断。当请求次数失败次数过多(服务中途挂掉,试验时是5次),将不再请求,直接返回CommonFallbackProvider配置的内容。

    当然,只要服务不可用,都会调用CommonFallbackProvider的方法返回信息,这就是服务降级。hystrix熔断是防止不断请求无效服务浪费资源,甚至影响其他服务。

    CommonFallbackProvider :

    package cn.pomit.springbootwork.config.client;
    package cn.pomit.springbootwork.consulzuul.config;
    
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.client.ClientHttpResponse;
    import org.springframework.stereotype.Component;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    import cn.pomit.springbootwork.consulzuul.model.ResultModel;
    
    @Component
    public class CommonFallbackProvider implements FallbackProvider {
        @Override
        public String getRoute() {
            return "*";
        }
    
        @Override
        public ClientHttpResponse fallbackResponse(String route, Throwable throwable) {
            throwable.printStackTrace();
            return new ClientHttpResponse() {
                @Override
                public HttpStatus getStatusCode() throws IOException {
                    return HttpStatus.OK;
                }
    
                @Override
                public int getRawStatusCode() throws IOException {
                    return 200;
                }
    
                @Override
                public String getStatusText() throws IOException {
                    return "OK";
                }
    
                @Override
                public void close() {
    
                }
    
                @Override
                public InputStream getBody() throws IOException {
                    ResultModel rm = ResultModel.error("服务咱不可用,请稍后重试!");
                    ObjectMapper mapper = new ObjectMapper();
                    return new ByteArrayInputStream(mapper.writeValueAsString(rm).getBytes());
                }
    
                @Override
                public HttpHeaders getHeaders() {
                    HttpHeaders headers = new HttpHeaders();
                    headers.setContentType(MediaType.APPLICATION_JSON);
                    return headers;
                }
            };
        }
    
    }
    
    

    四、开启Zuul代理

    在启动类似使用@EnableZuulProxy开启即可。

    ConsulZuulApplication :

    package cn.pomit.springbootwork.consulzuul;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    
    @EnableZuulProxy
    @EnableDiscoveryClient
    @EnableFeignClients
    @SpringBootApplication
    public class ConsulZuulApplication {
        public static void main(String[] args) {
            SpringApplication.run(ConsulZuulApplication.class, args);
        }
        
        @Bean
        @LoadBalanced
        RestTemplate restTemplate() {
            return new RestTemplate();
        }
    }
    
    

    五、其他web

    我们仍可以写自己的web服务,和zuul的转发互不影响,但是路径别重复了。
    ConsulZuulRest :

    package cn.pomit.springbootwork.consulzuul.web;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    import cn.pomit.springbootwork.consulzuul.model.ResultModel;
    
    @RestController
    @RequestMapping("/consulZuul")
    public class ConsulZuulRest {
        
        @RequestMapping(value = "/test", method = { RequestMethod.GET })
        public ResultModel ip() {
            return ResultModel.ok("非路由测试");
        }
    }
    
    

    六、Consul的健康检测

    这个是使用consul做注册中心才需要的。

    package cn.pomit.springbootwork.consulzuul.web;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/consulHeart")
    public class HealthWeb {
    
        @RequestMapping(value = "health", method = { RequestMethod.GET })
        public String health() {
            return "check health";
        }
        
    }
    
    

    七、使用到的实体

    ResultModel:

    
    

    详细完整的实体,可以访问品茗IT-博客《SpringCloud技术指南系列(十一)API网关之Zuul使用》进行查看

    品茗IT-博客专题:https://www.pomit.cn/lecture.html汇总了Spring专题Springboot专题SpringCloud专题web基础配置专题。

    快速构建项目

    Spring项目快速开发工具:

    一键快速构建Spring项目工具

    一键快速构建SpringBoot项目工具

    一键快速构建SpringCloud项目工具

    一站式Springboot项目生成

    Mysql一键生成Mybatis注解Mapper

    Spring组件化构建

    SpringBoot组件化构建

    SpringCloud服务化构建

    喜欢这篇文章么,喜欢就加入我们一起讨论SpringBoot使用吧!


    品茗IT交流群

    相关文章

      网友评论

        本文标题:SpringCloud技术指南系列(十一)API网关之Zuul使

        本文链接:https://www.haomeiwen.com/subject/jfltmctx.html