在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:ip-limiter开源软件地址:https://gitee.com/laofeng/ip-limiter开源软件介绍:ip-limiter一、 IP限流平台介绍1. 为什么要做IP限流 网络世界中,真实的用户与爬虫机器人等混杂在一起,正常的请求与异常请求也是相互交织,做为服务的提供方都希望请求来自于真实的用户的真实请求,这么才能够达到成本收益的最大化,但是总会有一些人来非法尝试获取提供方的信息,爬取有价值的数据供自己使用。作为数据的拥有者,肯定不希望自己的数据被非常利用,因为就需要做一些防御措施,达到数据保护的目的,IP限流就是其中一种比较有效的方案。因为通常用于爬取数据的爬虫机器人,都是在一台或者固定的几台服务器上执行的数据爬取操作(当然他可以购买更多的动态,只是会花更多的成本),针对这种访问量异常的IP进行记录和跟踪,然后就可以确认来自这些IP的请求是不是真实的用户请求了。 2. 要达到的目标
二、架构1. 交互架构 2. 实现架构 3. 系统模块
三、设计原则1. 高性能
2. 高可用
3. 高可扩展
4. 简单易用
四、存储设计系统默认设计只会保存最多一个小时的访问纬度数据,且每个应用的数据是存放在单的hashkey中的,因而单个应用数据量不大,且了访问上的高效性,此处就默认使用Redis做为存储,也支持扩展为使用其它的存储。 1. black-ips 用于存储全局黑名单IP的Key,存储结构为Hash,HashKey为IP,HashValue为对象com.eeeffff.limiter.common.vo.BlackIpVO,其定义的字段如下: 注: 每个应用的IP黑名单数据都会单独存储到不同的Key中,其命名规则为"应用名称-black-ips",如IP限制平台控制台的IP黑名单数据,保存的Key为:ip-limiter-dashboard-black-ips; 2. white-ips 用于存储全局白名单IP的Key,存储结构为Hash,HashKey为IP,HashValue为对象com.eeeffff.limiter.common.vo.WhiteIpVO,其定义的字段如下: 注: 每个应用的IP白名单数据都会单独存储到不同的Key中,其命名规则为"应用名称-white-ips",如IP限制平台控制台的IP白名单数据,保存的Key为:ip-limiter-dashboard-white-ips; 3. minute-access 用于存储所有接入了IP限流平台的应用客户端的每分钟的访问统计汇总的Key,存储结构为Hash,HashKey为代表访问的分钟,HashValue为对象List,com.eeeffff.limiter.common.vo.AccessVO定义的字段如下: 注: 每个应用的分钟访问纬度数据都会单独存储到不同的Key中,其命名规则为"应用名称-minute-access",如IP限制平台控制台的分钟访问纬度数据,保存的Key为:ip-limiter-dashboard-minute-access; 每个应用每个节点的的分钟访问纬度数据都会单独存储到不同的Key中,其命名规则为"应用名称-ip及端口-minute-access",如IP限制平台控制台的分钟访问纬度数据,保存的Key为:ip-limiter-dashboard-127.0.0.1:20520-minute-access; 4. ip-limit 用于存储全局IP QPS设置的Key,存储结构为Hash,HashKey为IP,HashValue为对象com.eeeffff.limiter.common.vo.IpLimitVO,其定义的字段如下: 注: 每个应用的IP QPS设置数据都会单独存储到不同的Key中,其命名规则为"应用名称-ip-limit",如IP限制平台控制台的IP白名单数据,保存的Key为:ip-limiter-dashboard-ip-limit; 5. registered-clients 用于存储注册到IP限流平台管理控制台的Key,存储结构为Hash,HashKey为应用名称,HashValue为对象Map,用于存储该应用所有注册的客户端,Map的Key为应用客户端的IP+端口,com.eeeffff.limiter.common.vo.Client对定义的字段如下: 6. ip-limiter-dashboard-master 用于存储IP限流平台的Master节点的Key,存储结构为普通的字符串,其值为当前master节点的IP+端口。 7. permitsPerSecondEachIp 用于存储每个IP默认的最大QPS值的Key,存储结构为普通的数字,其值为当每个IP默认的最大QPS值。 注: 每个应用都会单独存储IP默认值最大QPS值,存储结构为普通的数字,其值为当前应用每个IP默认的最大QPS值,存储每个应用默认访问QPS的Redis的Key命名规则为“应用名称-permitsPerSecondEachIp”,如ip-limiter-dashboard的key为"ip-limiter-dashboard-permitsPerSecondEachIp"。 五、系统设计1. IP限流Agent 该Agent用于集成到应用端,提供了一些方便性的功能,如IP访问数据的收集与上报、从远程控制台获取IP黑/白名单等; 每个节点本地默认保留60份以1分钟为纬度的访问统计数据,即保存60分钟以分钟为纬度统计的访问数据,默认保留60份以秒为统计纬度的访问数据,这都可以根据相应的配置项进行调整。 1)功能模块 2)限流算法 常用的限流算法有以下四种:
选择的算法为计数器(固定窗口)算法,因为我们的应用场景为单个IP的限流,而不是针对所有请求限流,且该算法实现简单,能够满足一定的突发情况的处理,该算法的实现类为com.eeeffff.limiter.core.interceptor.IpQpsRateLimiter。 3)核心功能IP流控请求合法性检查:确保IP的访问不会超过QPS的限制,如果是黑名单的IP直接拒绝访问,确保系统的安全性 本地访问数据的上报:目前只是以分纬度主动上报了每分钟IP的访问统计数据 从远程更新IP黑白名单及QPS限制配置:更新到的配置会存放在本地缓存中,以确保本地检查合法性访问的高效性 提供秒纬度访问统计接口:远程控制台可以调用本地以秒纬度统计的实时QPS,更方便的了解当前应用的运行情况 4)核心流程 请求合法性检查 注:IP白名单、IP黑名单及IP的QPS都是在本地内存或本地缓存中,没有远程的IO操作,因而该校验过程仅会对整体性能产生非常微弱的影响。 请求合法性检查 子逻辑之 IP白名单校验逻辑 请求合法性检查 子逻辑之 IP黑名单校验逻辑 请求合法性检查 子逻辑之 IP QPS超限访问校验及增加IP的访问量 请求合法性检查 子逻辑之 IP QPS超限访问校验及增加IP的访问量 子逻辑之 当前IP是否超限访问的判断 从远程更新配置 5)核心配置 #IP Limiter控制台的地址ip.limiter.core.dashboardAddress = 127.0.0.1:8080#当前服务器的IP地址ip.limiter.core.serverAddress = [不配置则自动获取,如果指定则例用指定值]#本地缓存中保留多少份以秒纬度统计的数据,单位为秒ip.limiter.core.secondsMetricLocalKeeped = 60#本地应用最多保留多少份以分钟为单位的统计,如值为60时,则表示本地会保留60份以分钟为统计纬度统计的访问最多的Ip,也可以理解为保留60分钟每分钟访问最多的Ip的统计ip.limiter.core.maxTopAccessMinutes = 60#IP的QPS限制配置及IP黑/白名单从远程控制台更新时间间隔,单位为毫秒ip.limiter.core.ipQpsLimitAndBlackIpUpdateTimeInterval = 10000 2. IP限流控制台 1)功能模块 2)核心功能 a)超限访问IP自动限制访问 针对超限访问的IP,会临时将其加入到黑名单中,以临时阻止其对系统的访问。 限制分为四个等级:
限制规则及限制升级规则:
b)IP黑/白名单的管理 支持针对指定应用设置IP黑/白名单,生效范围为指定的应用,也支持从全局上设置IP黑/白名单,应用到所有应用中,管理功能包括IP黑/白名单增加、删除、查询的操作。 c)IP的最大QPS管理 IP的最大QPS设置分为以下几块内容:
d)注册客户端健康检查 定期对注册到控制台中所有的应用及每个应用的所有节点进行健康检查,检查逻辑如下:
e)系统对自动增加为黑名单的IP进行自检
f)查询应用的实时访问情况 在控制台查询指定应用端节点的实时IP访问情况。 3)核心流程 a)注册客户端健康检查 b)系统对自动增加为黑名单的IP进行自检 4)核心配置 spring.boot.enableautoconfiguration=true#服务的端口号server.port = 8080spring.application.name = ip-limiter-dashboard#以下是Apollo需要的相关配置参数,如果使用Apollo做为配置中心,在Apollo中创建名为ip-limiter-dashboard的项目#通过Apollo启动,命令行要带对应的参数,如:#-Dspring.profiles.active=DEV -Dapollo.meta=http://apollo.dev.xxx.com:8072##该参数通过命令行传入,通过启动命令传入该参数,以便于支持多个不同的环境##active.env= DEV## 将 Apollo 配置加载提到初始化日志系统之前,需要托管日志配置时开启#apollo.bootstrap.eagerLoad.enabled = true## 应用全局唯一的身份标识#app.id = ip-limiter-dashboard## Apollo Meta Server 地址,通过启动命令传入该参数,以便于支持多个不同的环境##apollo.meta = http://apollo.dev.xxx.com:8072## 自定义本地配置文件缓存路径#apollo.cacheDir = ./config## 设置在应用启动阶段就加载 Apollo 配置#apollo.bootstrap.enabled = true## 注入 application namespace#apollo.bootstrap.namespaces = application#如果使用Apollo做为配置中心,将以下配置拷贝到Apollo中即可,并将其在当前配置文件中注释掉ip.limiter.dashboard.permitsPerSecondEachIp = 50ip.limiter.dashboard.maxTopAccessIps = 10ip.limiter.dashboard.maxRedisTopAccessIps = 50ip.limiter.dashboard.globalMaxRedisTopAccessIps = 50ip.limiter.dashboard.maxRedisTopAccessMinutes = 60ip.limiter.dashboard.globalMaxRedisTopAccessMinutes = 60ip.limiter.dashboard.redisLockMaxWaitMillis = 60000ip.limiter.dashboard.maxTopAccessMinutes = 30ip.limiter.dashboard.connectTimeout = 5000ip.limiter.dashboard.soTimeout = 5000ip.limiter.dashboard.maxConnTotal = 100ip.limiter.dashboard.maxConnPerRoute = 10ip.limiter.dashboard.maxHttpRetryTimes = 5ip.limiter.dashboard.httpRetryIntervalTime = 20ip.limiter.dashboard.appClientHealthCheckRate = 1ip.limiter.dashboard.systemAddBlackIpCheckRate = 1spring.redis.host = 192.168.12.111spring.redis.port = 6379spring.redis.password = 8lFvrZh7d7Ik8LtNwpBMakleishenspring.redis.database = 12spring.redis.timeout = 5000spring.redis.jedis.pool.max-idle = 8spring.redis.jedis.pool.min-idle = 0spring.redis.jedis.pool.max-wait = 8spring.redis.jedis.pool.max-active = 20ip.limiter.core.dashboardAddress = 127.0.0.1:8080 5)功能界面(单个应用)分纬度访问TOP统计 (单个应用)秒纬度访问TOP统计 (单个应用)IP白名单设置 (单个应用)IP黑名单设置 (单个应用)单个IP的QPS设置 (分局)分纬度访问TOP统计 (全局)黑名单设置 (全局)白名单设置 (全局)单个IP的QPS设置 六、IP限流平台的搭建1. 下载源码并安排 git clone https://gitee.com/laofeng/ip-limiter.gitcd ip-limiter 2. 修改必要的核心配置文件 首先需要启动IP限流控制台,IP限流控制台默认使用Redis做为存储,因而需要先对Redis进行配置,否则应用运行时会报错,修改IP控制台的核心配置文件ip-limiter-dashboard/src/main/resources/application.properties,只需要修改其中的redis配置,其它的都可以使用默认值,如下所示: spring.redis.host = 192.168.12.111spring.redis.port = 6379spring.redis.password = 8lFvrZh7d7Ik8LtNwpBMakleishenspring.redis.database = 12spring.redis.timeout = 5000spring.redis.jedis.pool.max-idle = 8spring.redis.jedis.pool.min-idle = 0spring.redis.jedis.pool.max-wait = 8spring.redis.jedis.pool.max-active = 20 3. 启动IP限流平台控制台 cd ip-limiter-dashboard./start.sh 注:启动会报一些与Apollo相关的警告,可以不用理会,这个是方便配置后续接入Apollo的,如果实在是不喜欢,可以在pom中删除Apollo的引入,并且删除Apollo相关的代码即可。 控制台访问地址:
4. 启动演示应用 演示应用的目录ip-limiter-samples,里面包括了三个演示应用,分别为:
这三种应用类型应该包含了大部份的应用类型,每种应用都有自己的一些不同的集成方式及特点。 1)启动ip-limiter-spring-boot-sample 首先进入ip-limiter-spring-boot-sample目录,通过以下命令启动: ./install.sh./start.sh 其默认的端口为10000,启动成功后,可以通过http://localhost:10000/hello访问验证,待控制台打印出往IP限流平台注册成功字样后,就可以在控制台的左上角的下拉框中看到该应用了。 2)启动ip-limiter-spring-mvc-sample 该演示应用为了启动上的方便,需要先在/etc/maven/setting.xml的pluginGroup中增加jetty的插件: <pluginGroups> <pluginGroup>org.mortbay.jetty</pluginGroup> </pluginGroups> 直接保存退出即可。 然后进入ip-limiter-spring-mvc-sample目录,通过以下命令启动: ./runJetty.sh 启动的过程中可能会报一些Jetty的错误,这个不需要理会,待启动完成后其默认的端口为10001,启动成功后可以通过http://localhost:10001/app/health访问验证,待控制台打印出往IP限流平台注册成功字样后,就可以在控制台的左上角的下拉框中看到该应用了。 3)启动ip-limiter-spring-boot-sample 首先进入ip-limiter-spring-boot-sample目录,通过以下命令启动: ./install.sh./start.sh 其默认的端口为10002,启动成功后,可以通过http://localhost:10002/api_hello/hello访问验证,该请求实通过网关访问http://localhost:10000/hello,因而ip-limiter-spring-boot-sample需要先启动才可以验证该应用,待控制台打印出往IP限流平台注册成功字样后,就可以在控制台的左上角的下拉框中看到该应用了。 七、应用的集成目前应用的最新版本为1.1.3。
引入限流依赖的客户端starter核心模块 <dependency> <groupId>com.eeeffff.limiter</groupId> <artifactId>ip-limiter-core-web</artifactId> <version>${ip-limiter-core.version}</version> </dependency> 其它的什么也不用做了,方便吧@_@。
Spring MVC应用的接入就会多一些步骤,不过也不麻烦。1)引入限流依赖的客户端starter核心模块 <dependency> <groupId>com.eeeffff.limiter</groupId> <artifactId>ip-limiter-core-web</artifactId> <version>${ip-limiter-core.version}</version> </dependency> 2)将IP限流平台的包加入扫描及增加Inteceptor 因为IP限流平台是基于Inteceptor的,在Spring的配置文件中增加如下配置: <context:component-scan base-package="com.eeeffff.limiter"></context:component-scan><mvc:interceptors> <ref bean="ipLimiterInterceptor" /></mvc:interceptors> 如果遇到了集成上的问题,可以参考ip-limiter-spring-mvc-sample示例应用。
Spring Gateway使用的是Netty做为通信模块,不能够像其它应用一样使用Inteceptor来实现,需要使用其本身的GlobalFilter结合WebFilter来实现,因而需要集成不同的包: <dependency> <groupId>com.eeeffff.limiter</groupId> <artifactId>ip-limiter-core-spring-gateway</artifactId> <version>${ip-limiter-core.version}</version> </dependency> 和普通的Spring Boot应用一样,也是不需要做任何事情,就是这么简单。 参与贡献
加入组织: 群图片如果过期了,请加13265554108,暗号ip-limiter,通过后再拉入群。 |
请发表评论