zoukankan      html  css  js  c++  java
  • SpringCloud从入门到进阶(五)——路由接入Zuul及其单点部署

    内容

      单体应用中各个模块拆分成独立的系统,逐步演变出微服务架构。为了屏蔽微服务内部的复杂调用,引入了Zuul作为微服务调用的统一入口。本文介绍了Zuul的常用配置和使用,并通过简单的演示进行了测试。

    版本

      IDE:IDEA 2017.2.2 x64

      JDK:1.8.0_171

      manve:3.3.3

      SpringBoot:1.5.9.RELEASE

      SpringCloud:Dalston.SR1

    适合人群

      ​Java开发人员

    说明

      转载请说明出处:SpringCloud从入门到进阶(五)——路由接入Zuul及其单点部署

      GitHub仓库地址: https://github.com/leo-zz/SpringCloudDemo/tree/master/Zuul

    参考

           Linux入门实践笔记(二)--Jar包运行与关闭

           SpringCloud从入门到进阶(二)——注册中心Eureka的伪分布式部署

    Zuul介绍

      路由器的概念想必大家都接触过——家庭上网必备无线路由器。它将手机、电脑等设备的联网请求转发到电信运行商的网关,实现设备的网络通信。Zuul是微服务架构中扮演路由角色的组件,它是基于JVM的路由器,同时是服务端的负载均衡器。所有的外部微服务请求都会经过Zuul,由Zuul根据URL的信息将请求转发给对应的微服务进行处理。

      Zuul内置了Ribbon和hystrix,从eureka中获取微服务实例的信息,由Ribbon确定接收请求的微服务实例。所有的请求都通过hystrix处理,因而可以通过Hystrix的监控工具观察请求熔断的情况。一旦接口熔断环路开启,Zuul将不会再将请求转发给该服务。

    项目路径

    pom.xml

      配置maven的依赖文件pom.xml,引入SpringBoot,SpringCloud,Eureka Client和Zuul的依赖,以及Spring Boot打包的Maven插件。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.leo</groupId>
        <artifactId>zuul</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <!-- 通过继承的方式引入spring boot  -->
        <!--parent标签用于指定父pom-->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.9.RELEASE</version>
        </parent>
    
        <!--properties标签用于声明一些常量,例如源码编码为UTF-8,输出代码也为UTF-8,Java版本为1.8-->
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
            <spring-cloud.version>Dalston.SR1</spring-cloud.version>
        </properties>
    
        <dependencies>
            <!--eureka client-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
            </dependency>
            <!--zuul组件实现网关的路由转发和负载均衡-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-zuul</artifactId>
            </dependency>
        </dependencies>
    
        <!--子Module不会继承该依赖,除非显示声明-->
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <!-- Spring Boot的Maven插件,使用Maven插件的方式来启动Spring Boot工程
    如果不添加该插件在使用mvn命令打包的jar有问题,执行时会报错:xxx.jar中没有主清单属性-->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </project>
    yaml

    ​   本示例以单点的方式部署Zuul,将所有profiles的公共配置提取到yaml文件的顶部,以便后期进行高可用版本的部署。此外进行了Eureka Client、Zuul路由,logback日志等相关内容的配置。

    Eureka Client的配置

    ​  eureka.instance.instance-id,配置了实例的id。

    ​  eureka.client.service-url.defaultZone,配置了Eureka Server集群的地址。

    Zuul路由的配置

    ​  zuul.prefix属性,为所有请求添加统一的前缀,默认为空串,即不添加前缀。可以通过该属性实现API接口的版本号控制,比如此处设置为"/v1"表示API接口为v1版本,注意前缀要以"/"开头。

    ​  zuul.routes属性,用于配置路由器的路由信息。其中的zuul.routes.path属性表示url的匹配规则,zuul.routes.serviceId表示处理该路由的微服务的application name。

    ​  本示例配置了两条路由,名称为routeA和routeB,分别将"/routea"和"/routeb"开头的url请求转发给微服务application-serviceA和application-serviceB进行处理。初次接触SpringCloud的童鞋要注意,这里的application-serviceA和application-serviceB都是微服务的应用名,即spring.application.name属性;不是eureka client的实例名称,eureka.instance.instance-id属性。

    日志的配置

      ​logging.file属性,配置了日志文件的位置和名称。日志的配置默认读取classpath下的logback-spring.xml。

    spring:
      application:
        name: application-gatewayservice
      profiles:
        active: peer1
    #Zuul的配置
    zuul:
      #通过zuul.prefix属性配置前缀,为所有请求添加统一的前缀,默认为空串,即不添加前缀。
      #可以通过该属性实现API接口的版本号控制,注意前缀要以"/"开头,此处设置为"/v1"表示API接口为v1版本。
      prefix: /v1
      #如果某服务存在多个实例,Zuul结合Ribbon会做负载均衡,将请求均分的部分路由到不同的服务实例
      #zuul.routes属性配置路由器的路由信息。
      routes:
        #路由的名称是用户自定义的,需要指定它的path和serviceld,二者规定了将指定规则的请求Url路由到指定的Serviceld
        #符合/routea/** 规则的请求转发给微服务springcloud-serviceA
        routeA:
          path: /routea/**
          serviceId: application-serviceA #此处是spring的applicationname,即Eureka的服务名,而非instance-id 实例名。
        #符合/routeb/** 规则的请求转发给微服务springcloud-serviceB
        routeB:
          path: /routeb/**
          serviceId: application-serviceB
    #指明日志存放位置
    logging:
      file: logs/application-gatewayservice-${server.port}.logs
    #配置了Eureka Server集群的地址
    eureka:
      client:
        service-url:
          defaultZone: http://172.26.125.114:7001/eureka,http://172.26.125.115:7001/eureka,http://172.26.125.118:7001/eureka
    ---
    spring:
      profiles: peer1
    server:
      port: 7081
    
    #Eureka实例名的配置
    eureka:
      instance:
        instance-id: springcloud-gatewayservice-A7-7081
    
    #actuator的配置
    management:
      port: 7181
      security:
        enabled: false
    
    ---
    spring:
      profiles: peer2
    server:
      port: 7082
    
    #Eureka实例名的配置
    eureka:
      instance:
        instance-id: springcloud-gatewayservice-A7-7082
    
    #actuator的配置
    management:
      port: 7182
      security:
        enabled: false

    logback-spring.xml

      本实例的日志按照日期、文件大小、日志级别进行分割,并将不同的级别或日期将记录到不同的日志文件中,并且日志的大小超过限定值后会自动切割,详细请参考SpringBoot从入门到进阶——学会Logback日志的配置和搭建,具体参数此处略去。

    SpringApplication

      主程序类中,增加@EnableZuulProxy开启Zuul路由功能。增加@EnableEurekaClient开启Eureka Client的功能。

    @EnableZuulProxy //开启Zuul的功能
    @EnableEurekaClient//开启Eureka Client的功能。
    @SpringBootApplication
    public class GatewayServiceApplicaton {
        public static void main(String[] args) {
            SpringApplication.run(GatewayServiceApplicaton.class,args);
        }
    }
    Zuul断路器 

      Zuul的自定义断路器,在请求路由的响应超时或请求失败后,Zuul会进行服务熔断,并执行MyFallbackProvider中配置的回调方法。本示例在回调函数中添加了统一的错误提示信息,断路器同时可以避免请求线程阻塞带来的服务雪崩的危害。

      ​MyFallbackProvider实现了ZuulFallbackProvider接口,通过实现其中的方法对断路器进行配置:

    ​  getRoute()方法用于配置该断路器匹配的请求的url规则,此处为"*",表示MyFallbackProvider会处理所有的路由请求。fallbackResponse()方法通过返回ClientHttpResponse接口的对象,ClientHttpResponse接口规定了回调响应的具体逻辑,表示返回到客户端的HTTP响应,包括HTTP状态码、响应头、响应体等信息。

    @Component
    public class MyFallbackProvider implements ZuulFallbackProvider {
    
        /**
         * getRoute()方法,用于指定熔断功能应用于哪些路由的服务。
         * 如果需要所有的路由服务都加熔断功能,只需要在getRoute()方法上返回"*"的匹配符,
         */
        @Override
        public String getRoute() {
            return "*"; //所有路由服务都增加熔断。
        }
    
        /**
         * fallbackResponse()为进入熔断功能时执行的逻辑
         */
        @Override
        public ClientHttpResponse fallbackResponse() {
            return new ClientHttpResponse() {
                //设置响应的HTTP状态码(HttpStatus中的enum值)
                @Override
                public HttpStatus getStatusCode() throws IOException {
                    return HttpStatus.SERVICE_UNAVAILABLE;
                }
    
                //设置响应的HTTP状态码(数字,可以是非标准的状态码)
                @Override
                public int getRawStatusCode() throws IOException {
                    return 503;
                }
    
                //设置响应的HTTP状态文本信息
                @Override
                public String getStatusText() throws IOException {
                    return "Service_Fallbcak";
                }
    
                //关闭响应,用于释放资源
                @Override
                public void close() {
    
                }
    
                //以输入流的形式返回响应体的信息
                @Override
                public InputStream getBody() throws IOException {
                    return new ByteArrayInputStream("您好,服务出现故障,请重试。".getBytes("utf-8"));
                }
    
                //返回响应头的信息
                @Override
                public HttpHeaders getHeaders() {
                    HttpHeaders headers = new HttpHeaders();
                    headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
                    return headers;
                }
            };
        }
    }

    启动与测试

      项目的打包、部署过程之前文档已经写明,可参考:SpringCloud从入门到进阶(二)——注册中心Eureka的伪分布式部署

    #启动jar包。
    [user@Serverjars]$ java -Dspring.profiles.active=peer1 -jar zuul-1.0-SNAPSHOT.jar

      访问eureka服务器,可以看到zuul微服务处于up状态,项目成功启动。

    1540277505269

      使用postman请求url"http://localhost:7081/v1/routea/upload",该url符合"/v1/routea/**",由路由规则可知,该url匹配路由routeA,会被转发到微服务springcloud-serviceA。但是由于微服务还未部署,因此请求对应接口会报503错误(走MyFallbackProvider执行服务熔断)。

      如果请求url不能匹配到zuul上的路由规则,则会报404错误。

    补充:使用Zipkin监控路由Zuul的请求处理。

      为了监控请求处理的耗时情况,会在路由端和微服务端增加链路追踪组件Zipkin,具体配置请参考后续章节。

  • 相关阅读:
    iOS 两个App之间调起通信
    iOS图片压缩处理
    c# XML和实体类之间相互转换(序列化和反序列化)
    asp代码获取年数,季度数.星期数,天数,小时数,分钟数,秒数等时
    C# 响应微信发送的Token验证,文字、图文自动回复、请求客服对话.....
    sql server2008 R2打开报错:无法识别的配置节 system.serviceModel解决办法分享
    html5/css3响应式布局介绍及设计流程
    C#从入门到精通视频教程(2009年最新) 视频列表
    视频播放flv player的使用
    ASP中DateDiff函数详解
  • 原文地址:https://www.cnblogs.com/lonelyJay/p/9842061.html
Copyright © 2011-2022 走看看