前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Cloud Zuul通过zuul-ratelimit实现限流

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

作者头像
胖虎
发布2019-06-26 17:14:13
3.1K0
发布2019-06-26 17:14:13
举报
文章被收录于专栏:晏霖
前言

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

本文 Demo 摘自《重新定义》

正文

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

限流粒度/类型

说明

User

针对请求的用户进行限流

Origin

针对请求的Origin进行限流

URL

针对URL/接口进行限流

ServiceId

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

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

存储方式

说明

IN_MEMORY

基于本地内存,底层是ConcurrentHashMap,默认的。

REDIS

基于redis存储,使用时必须搭建redis

CONSUL

consul 的kv存储

JPA

spring 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

代码语言:javascript
复制
<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 所有代码贴在一起

代码语言:javascript
复制
@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

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

代码语言:javascript
复制
@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:
代码语言:javascript
复制
  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

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

启动类

代码语言:javascript
复制
@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
public class ZuulServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ZuulServerApplication.class, args);
    }
}
pom依赖
代码语言:javascript
复制
<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文件

代码语言:javascript
复制
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 秒。这些参数大家根据你对需要自己修改。

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

代码语言:javascript
复制
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次会报错,后台也会抛错。

代码结构

需要第可以加微信

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-04-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 晏霖 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 正文
    • 代码示例
    相关产品与服务
    云数据库 Redis
    腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档