23. 从零用Rust编写正反向代理,流控小姐姐的温柔一刀!
wmproxy
wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,内网穿透,后续将实现websocket代理等,会将实现过程分享出来,感兴趣的可以一起造个轮子
项目地址
国内: https://gitee.com/tickbh/wmproxy
github: https://github.com/tickbh/wmproxy
温柔的小姐姐
我的名字叫 流控,至于我的工作你们看到我的名字也想必很清楚,我被创造出来为了的这世界更美好,期望这世界永远不会堵车,所以他们称我为温柔的小姐姐。
与数据不得不说的故事
数据是个急性子的家伙,每次看他总是充充忙忙的带着一大推的大部分,想在我这里横冲直撞的。这就不得不说上一次他那急忙的模样了。
还记得上次他带着一大帮的兄弟,成千上万个的,知道的人知道他们在护送重要资料,不知道的还以为他们去打仗呢!
我守护的是一个广场,还有广场后面的一条路。
那一次他带着兄弟来的太快,就跟我说:“流控姐姐,快点通往广场的门打开,我这边有兄弟们来了”。
我就把门打开,让他带着他的兄弟们过来快速的进入广场。
不一会儿广场慢慢的有点挤了起来,他就跟我说:“你快点把广场前面的路开大点,后面的兄弟来的太快,这条路又不能快速的通过,会把你的广场挤满的”。
我就说:“不行哦,我接到上级的指令,通知说现在这条路只能开这么大,每秒通过100人最多了(限速1M/S),前面那条大路现在的人太多了,你这边要是太多的人会全部堵在一起的。”
他就急忙的问:“那怎么办,我现在数据很重要,也很急,你看旁边那些无关的也一直在占用着路,你能不能向你的上级反馈一下?”
我就说:“我现在就帮你反馈一下,但是要等下上级的调度哦。暂时你还是只能通过这么多!”
我转身向上级说:“这边有大量的重要数据拥堵在广场这,他们请求调高优先级,提高缓冲区及通行速度。”
上级答:“我现在去协调一下,把其它的数据叫他们先缓缓,你叫他先耐心等待下”
眼看着上级的指定还没有下来,但是广场上已经快挤满了人了,我赶紧去那个广场的入口处理,我就把那个广场前的那个闸机打开,不让新的人进来。要不然等下广场出事故了。
数据兄弟看着我,我也表示我暂时也无能为力,我说:“让你后面的兄弟缓缓,我这广场暂时容纳不下那么多人了(数据缓冲区已满,不再接收新的数据,也不会读出socket上的数据,反向的压着流量的传输)。”
此时正在我们焦急等待的时候,上级传来了指令,说其它位置已经暂缓处理了,你当下可以把广场外围开起来,并把广场前面的路两边都放开(优先级调高,优先传输重要数据)。
我就立马启动了扩容的按钮,只见广场外围的大圈全部打开,可以容纳10倍的人,并把广场前的出口路打开,可以通行10000人/s(限速100M/S)。
数据说:“快快快,已经可以通行了,快把闸机打开,我要赶紧带着兄弟们把资料送到。”
只看到广场出去的人比进入的人多了很多,广场一下子空了起来。
很快数据就全部带着他的兄弟走了,去完成任务了,说:“等我完成这任务,我向你来讨教讨教你这边的管理法,怎么能保证高效的完成调度的任务”。
当起了老师
数据完成了他的任务,回来的时候在跟我请教了起来。
数据说:“我就是想问问,你的那个广场是怎么个情况,怎么一满了就可以自动防止人进入,然后一空了就可以通知人进入的。”
我跟他解答说:“我这是一个异步处理的一把刀,我可以在空闲的时候完全的不占用任何的资源,在忙碌的时候又可以把全部的CPU用上。完成高效的运转。”
数据问:“那你用了什么秘密法宝,他这么厉害?”
我说:“我就是用了一种古代就开始在用的——旗语,也就是PollSemaphore,我这里存一把旗,并存了一把钥匙,当我有钥匙的时候,也就是广场人没满的时间,你来了我就放你进场,这样子我也不用管广场里有没有满。当你进入后,如果 广场满了,他会将我手上的钥匙拿走。没有钥匙的话,新进来的人我就不会让你们进入了。”
数据问:“那如果广场有位置的话,那你怎么样才能重新得到钥匙?”
我说:“这就是我高效的时候了,刚刚我钥匙交出去的时候,我已经调用了self.sem.poll_acquire(cx),当广场有人出去的话,他就会通知Waker,然后我就可以主动去找他拿到钥匙了,这样子我就可以重新拥有钥匙了。”
数据说:“原来你缓冲区是这样子的吖,那你出口的那条路上,怎么限定人流量的?”
我说:“这个就要有请RateLimitLayer了,他有定义了per每个周期的时间就比如每秒,或者每分钟,或者每小时,nums就是每个周期内可以通行的字节数。下面是详细的定义。”
pub struct RateLimitLayer {
/// 周期内可以通行的数据
nums: u64,
/// 每个周期的时间
per: Duration,
/// 当前周期下,还剩下可通行的数据
left_nums: u64,
/// 下一个时间重新计算的日期
util: Instant,
sleep: Pin<Box<Sleep>>,
}
数据问:“那如果当前周期耗完的话,是不是还没有到下个周期前就不能继续通行了?”
我答:“确实是的,你当前周期耗光了可用的额度,那不能通行了哦,我就会向Pin::new(&mut self.sleep).poll(cx).is_pending(),如果他现在不能用,就等会到那个时间,他就会通知我啦。他通知我,我就会重置掉到前的数据,这样子你就可以继续通行了。”
self.left_nums = self.nums;
self.util = Instant::now() + self.per;
self.sleep.as_mut().set(tokio::time::sleep_until(Instant::now() + self.per));
数据说:“小姐姐你好厉害,还好有你在这里严格的控制着,我才能那么准时的到达”。
我答:“那是,请叫我温柔的一刀,该严格的时候我就会严格,不严格那只会更麻烦。你说是吧。”
流控在互联网中是很重要的概念,因为基本上大部分的公网出口都不是无限的,就同一个网站,API的接口重要性肯定会比静态文件重要性来的高,所以为了使系统更稳定,感谢流控小姐姐使出这温柔的一刀。
点击 [关注],[在看],[点赞] 是对作者最大的支持
23. 从零用Rust编写正反向代理,流控小姐姐的温柔一刀!的更多相关文章
- bloom-server 基于 rust 编写的 rest api cache 中间件
bloom-server 基于 rust 编写的 rest api cache 中间件,他位于lb 与api worker 之间,使用redis 作为缓存内容存储, 我们需要做的就是配置proxy,同 ...
- 正反向代理、负载均衡、Nginx配置实现
一.正反向代理 1.前提 我们曾经使用翻墙软件,访问google:使用了代理软件时,需要在浏览器选项中配置代理的地址,我们仅仅有代理这个概念,并不清楚代理还有正向和反向之分. 2.正向代理(代替客户端 ...
- 编写可编辑的List控件
今天由于项目的需要,要编写个能编辑的List控件,即双击List控件的表项能修改其中的内容.由于MFC自带的List控件是不能编辑的,所以在网上找了下怎样编写可编辑的CListCtrl控件,基本上都是 ...
- 重新想象 Windows 8 Store Apps (23) - 文件系统: 文本的读写, 二进制的读写, 流的读写, 最近访问列表和未来访问列表
原文:重新想象 Windows 8 Store Apps (23) - 文件系统: 文本的读写, 二进制的读写, 流的读写, 最近访问列表和未来访问列表 [源码下载] 重新想象 Windows 8 S ...
- BurpSuite 代理设置的小技巧
原文:https://www.anquanke.com/post/id/85925 作者:三思之旅 预估稿费:300RMB 投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿 在We ...
- 【技术分享】BurpSuite 代理设置的小技巧
作者:三思之旅 预估稿费:300RMB 投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿 在Web渗透测试过程中,BurpSuite是不可或缺的神器之一.BurpSuite的核心是 ...
- Nginx正反向代理、负载均衡等功能实现配置
版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 系统环境: VirtualBox Manager Centos6.4 nginx1.10.0 IP对应的机器名: IP ...
- 使用Squid部署代理缓存服务(标准正向、透明正反向代理)
正向代理让用户可以通过Squid服务程序获取网站页面等数据,具体工作形式又分为标准代理模式与透明代理模式.标准正向代理模式: 将网站的数据缓存在服务器本地,提高数据资源被再次访问时的效率,但用户必需在 ...
- 23、V4L2应用编写及各个ioctl涉及结构体说明分析
常用的结构体在内核目录include/linux/videodev2.h中定义 struct v4l2_requestbuffers //申请帧缓冲,对应命令VIDIOC_REQBUFSstruct ...
- 【源码】谷歌代理~WPF简单小软件-2015-10-15首发 (2016-03-01已更新源)
蛋疼,昨天把代理去了后才发现,原来咱们连谷歌应用都访问不了,,,用别人的总觉得不怎么安全,然后今天早上就编了个小软件干掉他这限制==> GoogleProxy.exe [主要目的:为了能在线安 ...
随机推荐
- 原生poi实现模版导出
背景 我们公司是内网开发,外网jar包我的权限不够,所以easyexcel jar包无法使用,参考了easyexcel的填充思想,写了一个较简单的填充方法,如果直接用easyexcel的话,可以参考这 ...
- 2021-10-08 Core的LaunchSettings文件说明
{ "iisSettings": { //是否以IIS Express启动 "windowsAuthentication": false, //是否启用wind ...
- chrome浏览器中使用adblockplus拦截广告
adblock plus是一款可以屏蔽广告以及任何你想屏蔽元素的软件,屏蔽之后的效果如下图所示,abp自动屏蔽广告,还可以自行添加屏蔽内容,右上角红色的ABP标识就是该软件 下载地址: htt ...
- 从零开始实现放置游戏(十七)——完结篇(附DEMO地址)
大家好,时隔2年多,我来填坑啦! 之前用的技术.设计思路都不成熟,所以直接干掉重做了. 由于从头教学实在太啰嗦,精力也有限,咱们还是直接上源码吧. DEMO地址: http://212.129.154 ...
- Spring HandlerInterceptor工作机制
本文以一个通过正常注册拦截器流程注册拦截器失败的实际场景,来带领大家阅读源码,体会Spring的HandlerInterceptor拦截器整个工作流程 简单认识 org.springframework ...
- 玄 - 利用DLL通知回调函数注入shellcode(上)
序 偶然看到某国外大佬发布新技术-"Threadless"进程注入技术,据说可过EDR(确实可),总结该技术原理 - 在远程目标进程中利用DLL通知回调机制执行shellcode, ...
- 作为用户我该如何调用API 接口获取商品数据
作为用户,如果你想要获取商品数据,可以通过调用API接口来实现.下面是一些步骤和注意事项,帮助你成功获取商品数据. 了解开放平台:首先,你需要了解开放平台,注册一个开发者账号,并创建一个应用.在创建应 ...
- 企业级低代码平台,通用代码生成平台,Java开源项目(附源码)
项目介绍 Jeecg-Boot 是一款基于代码生成器的智能开发平台!采用前后端分离架构:SpringBoot,Mybatis,Shiro,JWT,Vue&Ant Design.强大的代码生成器 ...
- Servlet 上
Servlet 1.什么是Servlet Servlet即Server Applet是运行在Web服务器端的小程序 2.创建Servlet的三种方式 注意:从Tomcat10.0以后,我们统一用 ja ...
- 从内核世界透视 mmap 内存映射的本质(原理篇)
本文基于内核 5.4 版本源码讨论 之前有不少读者给笔者留言,希望笔者写一篇文章介绍下 mmap 内存映射相关的知识体系,之所以迟迟没有动笔,是因为 mmap 这个系统调用看上去简单,实际上并不简单, ...