Getway网关管理ZUUL

Getway网关管理ZUUL

1.ZUUL微服务网关

微服务架构体系中,通常一个业务系统会有很多的微服务,比如:OrderService、ProductService、UserService...,为了让调用更简单,一般会在这些服务前端再封装一层,类似下面这样:

image.png

这样做,当然能跑起来,但是维护量大,以后各个微服务增加了新方法,都需要在网关层手动增加相应的方法封装,而spring cloud 中的zuul很好的解决了这一问题,示意图如下:

image.png

Zuul做为网关层,自身也是一个微服务,跟其它服务Service-1,Service-2, ... Service-N一样,都注册在eureka server上,可以相互发现,zuul能感知到哪些服务在线,同时通过配置路由规则(后面会给出示例),可以将请求自动转发到指定的后端微服务上,对于一些公用的预处理(比如:权限认证,token合法性校验,灰度验证时部分流量引导之类),可以放在所谓的过滤器(ZuulFilter)里处理,这样后端服务以后新增了服务,zuul层几乎不用修改。

2.代码实现:

代码的机构图如下:

image.png

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com</groupId>
    <artifactId>stu-zuul</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>stu-zuul</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <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>Finchley.RELEASE</spring-cloud.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-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.3.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>

    </dependencies>

    <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>

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

启动类:

StuZuulApplication:

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;

//启动类加上注解@EnableZuulProxy
//它默认加上了@EnableCircuitBreaker和@EnableDiscoveryClient
@SpringBootApplication
@EnableZuulProxy
public class StuZuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(StuZuulApplication.class, args);
    }
}

熔断器:

这个地方我用的springboot版本比较高,网上大部分是之前的版本的熔断器的配置,如果产生冲突可以看下是否有哦依赖版本冲突的问题:

MyFallbackProvider

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import com.netflix.hystrix.exception.HystrixTimeoutException;
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;

@Component
public class MyFallbackProvider implements FallbackProvider {
  @Override
  public String getRoute() {
    // 表明是为哪个微服务提供回退,*表示为所有微服务提供回退
    return "*";
  }

  @Override
  public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
    return null;
  }

  public ClientHttpResponse fallbackResponse(Throwable cause) {
    if (cause instanceof HystrixTimeoutException) {
      return response(HttpStatus.GATEWAY_TIMEOUT);
    } else {
      return this.fallbackResponse();
    }
  }
  public ClientHttpResponse fallbackResponse() {
    return this.response(HttpStatus.INTERNAL_SERVER_ERROR);
  }
  private ClientHttpResponse response(final HttpStatus status) {
    return new ClientHttpResponse() {
      @Override
      public HttpStatus getStatusCode() throws IOException {
        return status;
      }
      @Override
      public int getRawStatusCode() throws IOException {
        return status.value();
      }
      @Override
      public String getStatusText() throws IOException {
        return status.getReasonPhrase();
      }
      @Override
      public void close() {
      }
      @Override
      public InputStream getBody() throws IOException {
        return new ByteArrayInputStream("服务不可用,请稍后再试。".getBytes());
      }
      @Override
      public HttpHeaders getHeaders() {
        // headers设定
        HttpHeaders headers = new HttpHeaders();
        MediaType mt = new MediaType("application", "json", Charset.forName("UTF-8"));
        headers.setContentType(mt);
        return headers;
      }
    };
  }
}

bootstrap.yml:

server:
  port: 8040
spring:
  application:
    name: stu-zuul
eureka:
  client:
    service-url:
      defaultZone: http://user:password123@localhost:8761/eureka
  instance:
      prefer-ip-address: true
      instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
      hostname: localhost
      ip-address: localhost
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000
ribbon:
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #配置规则 轮询
  ConnectTimeout: 3000
  ReadTimeout: 60000
zuul:
  routes:
    api-a:
      path: /api-provider/**
      service-id: stu-provide
      sensitive-headers:
    api-b:
      path: /api-consumer/**
      service-id: stu-consumer,stu-consumer-feign-hytrix

上面已经讲到注解了@EnableZuulProxy后,它默认加上了@EnableCircuitBreaker和@EnableDiscoveryClient,

另外他是整合了ribbon的,不需要加额外的注解,但是可以配置相关的负载均衡的规则,下面的配置需要额外注意:

zuul:
  routes:
  #配置服务提供者的前缀,替代服务注册名,访问的时候就为http://localhost:8040/api-provider/**
    api-a:
      path: /api-provider/**
      service-id: stu-provide
      sensitive-headers:
    #配置消费者的前缀,替代服务注册名,访问的时候就为http://localhost:8040/api-consumer/**
    api-b:
      path: /api-consumer/**
      service-id: stu-consumer,stu-consumer-feign-hytrix

启动后进行访问,会得到相关提供者的信息.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏流柯技术学院

linux下安装rzsz

wget http://freeware.sgi.com/source/rzsz/rzsz-3.48.tar.gz

68110
来自专栏云原生架构实践

Jhipster技术栈定制 - 基于UAA的微服务之间安全调用

3个微服务都是通过Jhipster生成。 工程代码生成完之后,根据上一节启动的组件的实际情况,修改微服务配置文件中Eureka和database相关的配置。

1K30
来自专栏大数据和云计算技术

Flume日志收集系统架构详解

任何一个生产系统在运行过程中都会产生大量的日志,日志往往隐藏了很多有价值的信息。在没有分析方法之前,这些日志存储一段时间后就会被清理。随着技术的发展和分析能力的...

57780
来自专栏battcn

一起来学Spring Cloud(F版) | 第二篇:Ribbon软负载

Ribbon 是 Netflix 开源的基于 HTTP 和 TCP 的客户端负载均衡器框架,目前也已被 SpringCloud 团队集成在 spring-clo...

15330
来自专栏林德熙的博客

WPF 只允许打开一个实例

我们有时候只希望我们的程序只打开一个实例,也就是我们的软件只有一次被打开。 那么我们可以通过一个办法知道,在这个软件打开前是不是打开过一个,还没关闭。也就是是否...

22310
来自专栏Java3y

Druid数据库连接池就是这么简单

前言 本章节主要讲解Druid数据库连接池,为什么要学Druid数据库连接池呢?? 我的知识储备数据库连接池有两种->C3P0,DBCP,可是现在看起来并不够用...

558110
来自专栏IT笔记

Spring Cloud实战微服务精华视频教程

Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线...

660110
来自专栏极客编程

用Visual Studio Code和CLion进行EOS开发

每一个开发人员都需要一个良好的IDE,EOS开发也是一样,为项目开发过程构建一个良好的IDE环境是第一步。这就是为什么我们要写这个如何使用VS Code或者CL...

28220

使用NGINX反向代理部署Spring Boot应用

Spring Boot通过大量的默认配置,让使用Spring框架进行开发变得方便快捷,从而使得Java开发人员专注于程序原型设计。本文介绍如何创建一个简单的Sp...

1.2K30
来自专栏Java帮帮-微信公众号-技术文章全总结

Spring-拾遗

Junit集成 前面多次用到@RunWith与@ContextConfiguration,在测试类添加这两个注解,程序就会自动加载spring配置并初始化Spr...

32150

扫码关注云+社区

领取腾讯云代金券