Spring Cloud Zuul通过zuul-ratelimit实现限流

前言

本篇文章主要讲解 zuul-ratelimit 组件如何来作为服务限流的。并且只讲解他的默认存储类型,因为我想后期能力允许,我会单独讲解利用 redis 来做限流。

本文 Demo 摘自《重新定义》

 

正文

首先简单说一下 spring cloud zuul-ratelimit,他是外国人专门针对 zuul 编写的限流库,提供来4种限流策略,如下。

限流粒度/类型

说明

User

针对请求的用户进行限流

 Origin

针对请求的Origin进行限流

URL

针对URL/接口进行限流

ServiceId

针对服务进行限流,如果没有配置限流类型,则此类型生效

 

多种粒度临时变量储存方式

存储方式说明
IN_MEMORY基于本地内存,底层是ConcurrentHashMap,默认的。
REDIS基于redis存储,使用时必须搭建redis 
CONSULconsul 的kv存储
JPAspring data jpa,基于数据库
BUKET4J使用一个Java编写的基于令牌桶算法的限流库

这里重点说一下,如果 zuul 需要多节点部署,那就不能用 IN_MEMORY 存储方式,比较常用的就是用REDIS。

本篇Demo环境

框架

版本

Spring Boot

2.0.3.RELEASE

Spring Cloud

Finchley.RELEASE

zuul-ratelimit

2.0.6.RELEASE

JDK

1.8.x

 

代码示例

本篇案例一共涉及到一个父 pom 和三个工程,eureka-server    client-a    zuul-server

父pom

<modules>
		<module>ch8-3-eureka-server</module>
		<module>ch8-3-zuul-server</module>
		<module>ch8-3-client-a</module>
	</modules>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.3.RELEASE</version>
	</parent>
	
	<!--  利用传递依赖,公共部分  --> 
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<!-- springboot web -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
	</dependencies>

	<!-- 管理依赖 -->
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Finchley.RELEASE</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<!--注意: 这里必须要添加,否则各种依赖有问题 -->
	<repositories>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/libs-milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>

 

eureka-server

下面我把eureka-server 所有代码贴在一起

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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


server:
  port: 8888
eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/


<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
		</dependency>
	</dependencies>

 

client-a

由于当前客户端代码简单,我会把所有代码贴在一起

@SpringBootApplication
@EnableDiscoveryClient
public class ClientAApplication {
	
    public static void main(String[] args) {
        SpringApplication.run(ClientAApplication.class, args);
    }
}


@RestController
public class TestController {

	@GetMapping("/add")
	public Integer add(Integer a, Integer b){
		return a + b;
	}
	
	@GetMapping("/a/add")
	public Integer aadd(Integer a, Integer b){
		return a + b;
	}
	
	@GetMapping("/sub")
	public Integer sub(Integer a, Integer b){
		return a - b;
	}
	
	@GetMapping("/mul")
	public String mul(Integer a, Integer b){
		System.out.println("进入client-a!");
		return "client-a-" + a * b;
	}
	
	@GetMapping("/div")
	public Integer div(Integer a, Integer b){
		return a / b;
	}
}
server:
  port: 7070
spring:
  application:
    name: client-a
eureka:
  client:
    serviceUrl:
      defaultZone: http://${eureka.host:127.0.0.1}:${eureka.port:8888}/eureka/
  instance:
    prefer-ip-address: true

<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
	</dependencies>

 

zuul-server

下面重点讲解 网关这个工程

启动类

@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
public class ZuulServerApplication {

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

pom依赖

<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>com.marcosbarbero.cloud</groupId>
			<artifactId>spring-cloud-zuul-ratelimit</artifactId>
			<version>2.0.6.RELEASE</version>
		</dependency>
	</dependencies>

 

yml文件

spring:
  application:
    name: zuul-server
server:
  port: 5555
eureka:
  client:
    serviceUrl:
      defaultZone: http://${eureka.host:127.0.0.1}:${eureka.port:8888}/eureka/
  instance:
    prefer-ip-address: true
zuul:
  routes:
    client-a:
      path: /client/**
      serviceId: client-a
  ratelimit: 
#    key-prefix: springcloud-book #按粒度拆分的临时变量key前缀
    enabled: true #启用开关
#    repository: IN_MEMORY #key存储类型,默认是IN_MEMORY本地内存,必须大些
    behind-proxy: true #表示代理之后
    default-policy: #全局限流策略,可单独细化到服务粒度
      limit: 2 #在一个单位时间窗口的请求数量
      quota: 1 #在一个单位时间窗口的请求时间限制
      refresh-interval: 3 #单位时间窗口
#      type:
#        - user #可指定用户粒度
#        - origin #可指定客户端地址粒度
#        - url #可指定url粒度
   

代码解释:

我用 # 注释的代码可以不用写,除了上面注释的内容,我必须要整体说一下该配 置的含义,他表示对全局开启了限流,策略是,3秒内访问不允许超过 2 次,并且这 2 次请求要小于 1 秒。这些参数大家根据你对需要自己修改。

 

上面是对全局配置限流,下面我对其中一个服务进行限流,只需增加几行配置。

  ratelimit: 
    key-prefix: springcloud-book #按粒度拆分的临时变量key前缀
    enabled: true #启用开关
    repository: IN_MEMORY #key存储类型,默认是IN_MEMORY本地内存,此外还有多种形式
    behind-proxy: true #表示代理之后
    default-policy: #全局限流策略,可单独细化到服务粒度
      limit: 2 #在一个单位时间窗口的请求数量
      quota: 1 #在一个单位时间窗口的请求时间限制
      refresh-interval: 3 #单位时间窗口
      type: 
        - user #可指定用户粒度
        - origin #可指定客户端地址粒度
        - url #可指定url粒度

    policies:
      client-a:
      limit: 5
      quota: 5
      efresh-interval: 10

代码解释:

我们增加了 policies 配置,含义是我们对  client-a 服务进行特殊限流配置,10秒内请求数量不得大于 5 次,这 5 次请求总时长不能大于 5秒,其他服务对限流策略还是按照 上面默认的,不冲突。

 

测试

下面我们分别启动 eureka服务,客户端,zuul,因为我两种方法都已经试验过了,结果是一样的,比如 要求是 10 秒内请求 5 次,那么一定是第6次会报错,后台也会抛错。

 

 

代码结构

需要第可以加微信

 

 

  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值