SpringCloud Zuul 应用

荒凉一梦 提交于 2020-01-13 21:41:40

一:创建 eureka-zuul-client 服务

1.1 在主Maven工程中创建一个新的 Module 工程,命名为eureka-zuul-client。采用Spring Initializr 的方式的方式创建。
在这里插入图片描述
1.2 eureka-zuul-client 的 pom.xml 的内容如下:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.springcloud</groupId>
        <artifactId>springcloud-hx</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>eureka-zuul-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka-zuul-client</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.vaadin.external.google</groupId>
            <artifactId>android-json</artifactId>
            <version>0.0.20131108.vaadin1</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

1.3 主Module 的 的 pom.xml 加上:
在这里插入图片描述
1.4 eureka-zuul-client 的 配置文件 application.yml 的内容如下:

server:
  port: 8768

spring:
  #配置程序名为eureka-zuul-client
  application:
    name: eureka-zuul-client

eureka:
  client:
    #服务注册地址
    serviceUrl:
      #注意: Eureka Server 的注册地址
      #将服务提供者注册到三个Eureka Server中去
      #defaultZone: http://peer1:8001/eureka/,http://peer2:8002/eureka/,http://peer3:8003/eureka/
      #defaultZone: http://peer1:8001/eureka/
      defaultZone: http://localhost:8761/eureka/


#spring-cloud-starter-zuul依赖时,它自身就包含了对 spring-cloud-starter-hystrix 和 spring-cloud-starter-ribbon模块的依赖,
#所以 Zuul天生就拥有线程隔离和断路器的自我保护功能,以及 对服务调用的客户端负载均衡功能。
zuul:
  routes:
    #这两个配置可以将以 "/hiApi" 开头的Url 路由到 eureka-client服务。zuul.routes.hiApi 中的"hiApi"是自己定义的
    #如果某服务存在多个实例,Zuul结合ribbon 会做负载均衡
    hiApi:
      path: /hiApi/**
      serviceId: eureka-client
    ribbonApi:
      path: /ribbonApi/**
      sereviceId: eureka-ribbon-client
    feignApi:
      path: /feignApi/**
      serviceId: eureka-feign-client
    feignHystrixApi:
      path: /feignHystrixApi/**
      serviceId: eureka-feign-hystrix-client
  #给每一个服务的API接口加前缀
  prefix: /v1

ribbon:
  ReadTimeout: 60000
  ConnectTimeout: 60000

1.5 在启动类上加上 @EnableDiscoveryClient 开启服务注册于发现,加上@EnableZuulProxy //开启Zuul 的功能,代码如下:

package com.example.eurekazuulclient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
//开启服务注册于发现
@EnableDiscoveryClient
//开启Zuul 的功能
@EnableZuulProxy
public class EurekaZuulClientApplication {

	public static void main(String[] args) {
		SpringApplication.run(EurekaZuulClientApplication.class, args);
	}

}

1.6 启动 eureka-serve, eureka-client (8762,8763 端口),eureka-zuul-client ,eureka-feign-hystrix-client 服务,浏览器访问 http://localhost:8761/
在这里插入图片描述
多次访问http://localhost:8768/v1/hiApi/HiController/hi/java,得到如下结果:
在这里插入图片描述
在这里插入图片描述
可以看出,实现了负载均衡。

访问http://localhost:8768/v1/feignHystrixApi/FeignHystrixController/hi/java
在这里插入图片描述

1.7 在 Zuul 上配置熔断器
默认情况下,经过Zuul的请求都会使用Hystrix进行包裹,所以Zuul本身就具有熔断器的功能。
所以当我们的zuul进行路由分发时,如果后端服务没有启动,或者调用超时,我们可以进行熔断处理。
如何实现:实现 FallbackProvider 接口,实现该接口的getRoute() 和 fallbackResponse() 方法。
新建一个MyFallbackHystrix类,代码如下:

package com.example.eurekazuulclient.hystrix;

import org.json.JSONException;
import org.json.JSONObject;
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 java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 *默认情况下,经过Zuul的请求都会使用Hystrix进行包裹,所以Zuul本身就具有熔断器的功能。
 *所以当我们的zuul进行路由分发时,如果后端服务没有启动,或者调用超时,我们可以进行熔断处理。
 *如何实现:实现 FallbackProvider 接口,实现该接口的getRoute() 和 fallbackResponse() 方法
 */
@Component
public class MyFallbackHystrix implements FallbackProvider {

    /**
     * 返回值表示需要针对此微服务做熔断功能
     * (该名称一定要是注册进入 eureka 微服务中的那个 serviceId 名称);
     *
     * @return
     */
    @Override
    public String getRoute() {
        //api服务id,如果需要所有调用都支持回退,则return "*"或return null
        return "*";

    }


    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {

            @Override
            public HttpStatus getStatusCode() throws IOException {

                return HttpStatus.OK;
            }

            @Override
            public int getRawStatusCode() throws IOException {

                return HttpStatus.OK.value();
            }

            @Override
            public String getStatusText() throws IOException {

                return HttpStatus.OK.getReasonPhrase();
            }

            @Override
            public void close() {
            }

            /**
             * 当 springms-provider-user 微服务出现宕机后,客户端再请求时候就会返回 fallback 等字样的字符串提示;
             * 但对于复杂一点的微服务,我们这里就得好好琢磨该怎么友好提示给用户了;
             * 如果请求用户服务失败,返回什么信息给消费者客户端
             * @return
             * @throws IOException
             */
            @Override
            public InputStream getBody() throws IOException {
                /*JSONObject r = new JSONObject();
                try {
                    r.put("state", "9999");
                    r.put("msg", "系统错误,请求失败");
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                return new ByteArrayInputStream(r.toString().getBytes("UTF-8"));*/
                return new ByteArrayInputStream((getRoute() + " 出错了").getBytes());
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                //和body中的内容编码一致,否则容易乱码
                headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
                return headers;
            }
        };
    }

}

浏览器访问:http://localhost:8768/v1/feignHystrixApi/FeignHystrixController/hi/java
在这里插入图片描述

关闭 eureka-client 服务,再次访问,
在这里插入图片描述
这时,我们会发现,没有返回fallbackResponse类中的回调信息,而是返回了 eureka-feign-hystrix-client 项目 中 熔断器的回调信息。

接着,我们重新开启 eureka-client 服务,这次关闭 eureka-feign-hystrix-client 这个服务,再次访问:
在这里插入图片描述
这时候, eureka-zuul-client中 fallbackResponse 的返回生效了。

所以可以发现,eureka-feign-hystrix-client 熔断器的回调执行 > eureka-zuul-client 熔断器的回调执行。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!