最新要闻
- 每日看点!电动牙刷别乱买 买错代价太大了
- 全球即时:小鹏P7迎整车OTA:6项新增功能 360全景影像正式上线
- 世界热消息:挑战不可能!阿维塔11在“8D山城”重庆开启城区NCA智驾导航辅助体验
- 汽车促销潮蔓延 车险会降价吗?业内人士:没有直接影响
- 环球时讯:成都双流现飞机“横穿马路” 网友:真“飞”机动车道
- 钦州白癜风专科医院哪个好-白癜风患者如何缓解压力
- 全国18省份都有扬沙浮尘天气!沙尘暴趁夜入京:口罩挡不住行人吃土
- 今日要闻!乘联会:汽车价格没崩盘 降价潮不存在
- 天天简讯:别回家充电!电动车爆炸致死楼上邻居 全国又有多起发生:实测起火后可怕
- 热推荐:中科大研发镧系新型固态电解质 全固态锂金属电池新突破
- 每日消息!聚焦京津冀协同发展|培育农业品牌 让河北新鲜蔬菜装进北京“菜篮子”
- 机械鼠标看了心动?智商税别再交了!
- 特斯拉将取消强制单踏板模式 选择权终于交还用户
- 环球实时:江苏封杀“老头乐” 国内多省或效仿:倒逼大爷买新能源车、考驾照现实吗
- 每日热门:《GTA6》想超越“三男一狗”很难 三主角影响力太强
- 快看:大家可以来介绍家里杨过的过程,供大家参考吗?
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
环球速讯:如何用Golang处理每分钟100万个请求
用Golang处理每分钟100万个请求
转载请注明来源:https://janrs.com/9yaq
面临的问题
在我设计一个分析系统中,我们公司的目标是能够处理来自数百万个端点的大量POST请求。web 网络处理程序将收到一个JSON文档,其中可能包含许多有效载荷的集合,需要写入Amazon S3,以便我们的地图还原系统随后对这些数据进行操作。
(资料图片)
传统上,我们会研究创建一个工人层架构,利用诸如以下东西:
- Sidekiq
- Resque
- DelayedJob
- Elasticbeanstalk Worker Tier
- RabbitMQ
- 还有等等其他的技术手段...
并设置 2 个不同的集群,一个用于 Web 前端,另一个用于 worker 处理进程,这样我们就可以扩大我们可以处理的后台工作量。
但从一开始,我们的团队就知道我们应该在 Go 中这样做,因为在讨论阶段我们看到这可能是一个非常大的流量系统。 我使用 Go 已有大约 2 年左右的时间,我们公司在处理业务时开发了一些系统,但没有一个能承受如此大的负载。以下是优化的过程。
我们首先创建一些结构体来定义我们将通过 POST 调用接收的 Web 请求负载,以及一种将其上传到我们的 S3 存储桶的方法。代码如下:
type PayloadCollection struct {WindowsVersion string `json:"version"`Token string `json:"token"`Payloads []Payload `json:"data"`}type Payload struct { // ...负载字段}func (p *Payload) UploadToS3() error {// storageFolder 方法确保在我们在键名中获得相同时间戳时不会发生名称冲突storage_path := fmt.Sprintf("%v/%v", p.storageFolder, time.Now().UnixNano())bucket := S3Bucketb := new(bytes.Buffer)encodeErr := json.NewEncoder(b).Encode(payload)if encodeErr != nil {return encodeErr}// 我们发布到 S3 存储桶的所有内容都应标记为“私有”var acl = s3.Privatevar contentType = "application/octet-stream"return bucket.PutReader(storage_path, b, int64(b.Len()), contentType, acl, s3.Options{})}
使用 Go 协程
最初我们采用了一个非常简单的 POST 处理程序实现,只是试图将job 处理程序并行化到一个简单的 goroutine 中:
func payloadHandler(w http.ResponseWriter, r *http.Request) {if r.Method != "POST" {w.WriteHeader(http.StatusMethodNotAllowed)return}// 将body读入字符串进行json解码var content = &PayloadCollection{}err := json.NewDecoder(io.LimitReader(r.Body, MaxLength)).Decode(&content)if err != nil {w.Header().Set("Content-Type", "application/json; charset=UTF-8")w.WriteHeader(http.StatusBadRequest)return}// 分别检查每个有效负载和队列项目以发布到 S3for _, payload := range content.Payloads {go payload.UploadToS3() // <----- 这是不建议的做法。这里是最开始的做法。}w.WriteHeader(http.StatusOK)}
对于中等负载,这可能适用于大多数公司的流量,但很快证明这在大规模情况下效果不佳。 我们期望有很多请求,但没有达到我们将第一个版本部署到生产环境时开始看到的数量级。 我们完全低估了流量。
上面的方法在几个不同的方面是不好的。 无法控制我们生成了多少个 go routines。 由于我们每分钟收到 100 万个 POST 请求,因此这段代码很快崩溃了。
进一步优化
我们需要找到一种不同的方式。 从一开始我们就开始讨论我们需要如何保持请求处理程序的生命周期非常短,并在后台进行生成处理。 当然,这是你在使用 Ruby on Rails 时必须做的,否则你将阻止所有可用的 worker web 处理器,无论你使用的是 puma、unicorn 还是 passenger(请不要进入 JRuby 讨论)。 然后我们需要利用常见的解决方案来做到这一点,例如 Resque、Sidekiq、SQS 等等,有很多方法可以实现这一点。
所以第二次迭代是创建一个缓冲通道,我们可以创建一些队列,然后把 job push到队列并将它们上传到 S3,并且由于我们可以控制job 队列中的最大数数量并且我们有足够的内存来处理队列中的 job。在这个方案中,我们认为只需要在通道队列中缓冲需要处理的 job 就可以了。
代码如下:
var Queue chan Payloadfunc init() { Queue = make(chan Payload, MAX_QUEUE)}func payloadHandler(w http.ResponseWriter, r *http.Request) { ... // 分别检查每个有效负载和队列项目以发布到 S3 for _, payload := range content.Payloads { Queue <- payload // <----- 这是建议的做法。 } ...}
然后为了实际出列作业并处理它们,我们使用了类似的东西:
func StartProcessor() { for { select { case job := <-Queue: job.payload.UploadToS3() // <-- 这里虽然优化了,但还不是最好的。 } }}
在上面的代码中,我们用一个缓冲队列来交换有缺陷的并发性,而缓冲队列只是推迟了问题。 我们的同步处理器一次只将一个有效负载上传到 S3,并且由于传入请求的速率远远大于单个处理器上传到 S3 的能力,我们的 job 缓冲通道很快达到了极限并阻止了请求处理程序的能力,队列很快就阻塞满了。
我们只是在避免这个问题,并开始倒计时,直到我们的系统最终死亡。 在我们部署这个有缺陷的版本后,我们的延迟率在几分钟内以恒定的速度持续增加。以下是延迟率增长图:
更好的解决方案
我们决定在使用 Go 通道时使用一种通用模式,以创建一个 2 层通道系统,一个用于 Job 队列,另一个用于控制同时在 Job 队列上操作的 Worker 的数量。
这个想法是将上传到 S3 的数据并行化到某种程度上可持续的速度,这种速度既不会削弱机器也不会开始从 S3 生成连接错误。 所以我们选择创建 Job/Worker 模式。 对于那些熟悉 Java、C# 等的人来说,可以将其视为 Golang 使用通道实现 Worker 线程池的方式。
代码如下:
var (MaxWorker = os.Getenv("MAX_WORKERS")MaxQueue = os.Getenv("MAX_QUEUE"))// Job 表示要运行的作业type Job struct {Payload Payload}// 我们可以在 Job 队列上发送工作请求的缓冲通道。var JobQueue chan Job// Worker 代表执行作业的 Worker。type Worker struct {WorkerPool chan chan JobJobChannel chan Jobquit chan bool}func NewWorker(workerPool chan chan Job) Worker {return Worker{WorkerPool: workerPool,JobChannel: make(chan Job),quit: make(chan bool)}}// Start 方法为 Worker 启动循环监听。监听退出信号以防我们需要停止它。func (w Worker) Start() {go func() {for {// 将当前 woker 注册到工作队列中。w.WorkerPool <- w.JobChannelselect {case job := <-w.JobChannel:// 接收 work 请求。if err := job.Payload.UploadToS3(); err != nil {log.Errorf("Error uploading to S3: %s", err.Error())}case <-w.quit:// 接收一个退出的信号。return}}}()}// 将退出信号传递给 Worker 进程以停止处理清理。func (w Worker) Stop() {go func() {w.quit <- true}()}
我们已经修改了我们的 Web 请求处理程序,以创建一个带有有效负载的 Job 结构实例,并将其发送到 JobQueue 通道以供 Worker 提取。
func payloadHandler(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" {w.WriteHeader(http.StatusMethodNotAllowed)return} // 将body读入字符串进行json解码var content = &PayloadCollection{}err := json.NewDecoder(io.LimitReader(r.Body, MaxLength)).Decode(&content) if err != nil {w.Header().Set("Content-Type", "application/json; charset=UTF-8")w.WriteHeader(http.StatusBadRequest)return} // 分别检查每个有效负载和队列项目以发布到 S3 for _, payload := range content.Payloads { // 创建一个有效负载的job work := Job{Payload: payload}// 将 work push 到队列。 JobQueue <- work } w.WriteHeader(http.StatusOK)}
在我们的 Web 服务器初始化期间,我们创建一个 Dispatcher 调度器并调用 Run() 来创建 Woker 工作池并开始侦听将出现在 Job 队列中的 Job。
dispatcher := NewDispatcher(MaxWorker) dispatcher.Run()
下面是我们的调度程序实现的代码:
type Dispatcher struct {// 通过调度器注册一个 Worker 通道池WorkerPool chan chan Job}func NewDispatcher(maxWorkers int) *Dispatcher {pool := make(chan chan Job, maxWorkers)return &Dispatcher{WorkerPool: pool}}func (d *Dispatcher) Run() {// 启动指定数量的 Workerfor i := 0; i < d.maxWorkers; i++ {worker := NewWorker(d.pool)worker.Start()}go d.dispatch()}func (d *Dispatcher) dispatch() {for {select {case job := <-JobQueue:// 接收一个 job 请求go func(job Job) {// 尝试获取可用的 worker job 通道// 这将阻塞 worker 直到空闲jobChannel := <-d.WorkerPool// 调度一个 job 到 worker job 通道jobChannel <- job}(job)}}}
请注意,我们提供了要实例化并添加到我们的 Worker 池中的最大worker 数量。 由于我们在这个项目中使用了 Amazon Elasticbeanstalk 和 dockerized Go 环境,因此我们从环境变量中读取这些值。 这样我们就可以控制 Job 队列的数量和最大大小,因此我们可以快速调整这些值而无需重新部署集群。
var ( MaxWorker = os.Getenv("MAX_WORKERS") MaxQueue = os.Getenv("MAX_QUEUE"))
在我们部署它之后,我们立即看到我们所有的延迟率都下降到极低的延迟,并且我们处理请求的能力急剧上升。以下是流量截图:
在我们的弹性负载均衡器完全预热几分钟后,我们看到我们的 ElasticBeanstalk 应用程序每分钟处理近 100 万个请求。 我们通常在早上有几个小时的流量会飙升至每分钟超过一百万。
一旦我们部署了新代码,服务器数量就从 100 台服务器大幅下降到大约 20 台服务器。以下是服务器数量变化截图:
在正确配置集群和自动缩放设置后,我们能够将其进一步降低到仅 4x EC2 c4.Large 实例,并且如果 CPU 使用率超过 90% 持续 5 天,Elastic Auto-Scaling 将生成一个新实例 分钟值。以下是截图:
总结
可以看出利用 Elasticbeanstalk 自动缩放的强大功能以及 Golang 提供的开箱即用的高效和简单的并发方法,就可以构建出一个高性能的处理程序。
转载请注明来源:https://janrs.com/9yaq
关键词:
-
天天热点评!全网最详细中英文ChatGPT-GPT-4示例文档-步骤指示智能生成从0到1快速入门——官网推荐的48种最佳应用场景(附python/node.js
ChatGPT可以非常方便地将自然语言转换为逐向指示,帮助人们更好地理解和使用语言。它可以根据复杂的提示...
来源: -
【高端访谈】“与时俱进”|绿债担保品管理驱动绿色金融体系建设升级——专访中央结算公司担保品业务负责人
近两年来,绿债担保品管理理念在我国金融市场得到深入应用,有效缓解绿债市场流动性不足、投融资成本高...
来源: 环球速讯:如何用Golang处理每分钟100万个请求
天天热点评!全网最详细中英文ChatGPT-GPT-4示例文档-步骤指示智能生成从0到1快速入门——官网推荐的48种最佳应用场景(附python/node.js
【高端访谈】“与时俱进”|绿债担保品管理驱动绿色金融体系建设升级——专访中央结算公司担保品业务负责人
每日看点!电动牙刷别乱买 买错代价太大了
全球即时:小鹏P7迎整车OTA:6项新增功能 360全景影像正式上线
世界热消息:挑战不可能!阿维塔11在“8D山城”重庆开启城区NCA智驾导航辅助体验
汽车促销潮蔓延 车险会降价吗?业内人士:没有直接影响
环球时讯:成都双流现飞机“横穿马路” 网友:真“飞”机动车道
钦州白癜风专科医院哪个好-白癜风患者如何缓解压力
通过Nginx定义Header头信息
全国18省份都有扬沙浮尘天气!沙尘暴趁夜入京:口罩挡不住行人吃土
今日要闻!乘联会:汽车价格没崩盘 降价潮不存在
天天简讯:别回家充电!电动车爆炸致死楼上邻居 全国又有多起发生:实测起火后可怕
热推荐:中科大研发镧系新型固态电解质 全固态锂金属电池新突破
每日消息!聚焦京津冀协同发展|培育农业品牌 让河北新鲜蔬菜装进北京“菜篮子”
【读财报】两年持有期基金回撤透视:广发、上投摩根基金等产品亏损幅度居前
四大证券报精华摘要:4月11日
机械鼠标看了心动?智商税别再交了!
特斯拉将取消强制单踏板模式 选择权终于交还用户
环球实时:江苏封杀“老头乐” 国内多省或效仿:倒逼大爷买新能源车、考驾照现实吗
每日热门:《GTA6》想超越“三男一狗”很难 三主角影响力太强
每日速看!学系统集成项目管理工程师(中项)系列04a_项目管理一般知识(上)
快看:大家可以来介绍家里杨过的过程,供大家参考吗?
环球热消息:国产战机大片《长空之王》新预告公布:看完热血
天天热推荐:重学c#系列—— 简单编写一个guid [娱乐篇]
环球热议:乘联会:新能源车绿牌2年内或消失 但不是因为它难看
全球热议:男子网购耐克鞋挂李宁吊牌?平台回应:员工绑错了
精选!工匠精神又崩了 日本知名寿司店常年用过期食材:肉眼看不出变色就能用
环球热点!迪士尼《小美人鱼》新剧照出炉:人鱼对比高颜值反派公主 你选谁?
特斯拉在韩推出Model S/X 比国内便宜 约64.85万元起
名记:法国足球可能给梅西颁发超级金球奖 历史仅1人获此荣誉
【世界快播报】台州多地发布事业单位招聘公告
每日快报!小程序开发,uni-app,XBuilder 学习资源
天天新动态:前端工程化实战:React 模块化开发、性能优化和组件化实践
每日时讯!ADMM——交替方向乘子法
全球速递!中小型项目请求限流设计
天天新消息丨电动车价格有得降!“白色石油”碳酸锂价格雪崩:有公司濒临破产
世界快资讯丨局地阵风10级!北京发布大风沙尘暴双黄色预警:空气质量严重污染
全球消息!解释一下布隆过滤器原理
世界通讯!mit 6.824 lab1分析
每日热点:AQS源码学习
环球播报:日本拉面店禁止边吃边看手机!店长给出的理由看醉了:有损厨师尊严
4个月了!AMD RX 7900 XTX旗舰卡终于降价:一度杀到6399元 降幅20%
世界快播:Nimo全球盛典圆满举行 提速布局全球化业务
最新:screenfetch报错 /usr/bin/screenfetch: 行 1851: -: 语法错误:需要操作数(错误记号是 "-") 的一种解决方法
天天精选!直线光栅化-Bresenham算法
当前观点:客车司机开车途中嗦粉吓坏乘客 双手离开方向盘:官方回应
HTC发布Wildfire入门级4G手机:国产展锐处理器、3G内存
焦点速看:中国人自己的智能车身控制系统!比亚迪云辇实现0-1突破:填补国内技术空白
全球时讯:比亚迪云辇发布 王传福:传统豪华看车标、新能源豪华看技术
全球车身控制技术最高水平:比亚迪U9搭云辇X“跳舞”登台
伊宝馨2022年净利3220.96万同比增长161.43% 销售规模增加
天天视讯!百度松果菁英班--oj赛(第一次)
观点:未势能源首发“木星”车载液氢储氢系统:一罐氢气续航超1000km
最新消息:你掉的不是头发 而是“钻石”!
世界速读:长辈送礼绝不踩坑!平仄普洱茶大促:高档礼盒装到手99元
就等小米13 Ultra发布了!米粉晒工资:称“资金已到位”
比亚迪云辇技术来了:四套系统 汽车会自己“看路”
焦点速读:Android开发_记事本(2)数据库
领失业金的年轻人,重新思考工作的意义
看点:北上高铁出现大规模晚点 官方回应:故障抢修完毕 有序恢复通行
环球快讯:马斯克离开OpenAI内幕:大权独揽想法被拒 10亿美元打水漂
形同灾难电影!四子王旗沙尘暴红警:天空变橙红色
全球时讯:好吃无负担:诺梵55%~100%黑巧巧克力9.9元大促
全球今头条!Windmill 搭建个人任务中心
环球微头条丨市建局协办活动 重塑龙城特色风情
环球快播:水平接近ChatGPT!昆仑万维国产大语言模型“天工”3.5来了
世界热门:《铁甲小宝》高清重制引热议 网友:这次好好看看小姐姐
苦等703天后 《生化危机8村庄》Denuvo加密移除:正版玩家终于不卡了
售价20多万续航仅160公里 日系车工业垃圾果然凉凉:今年只卖出15辆
环球新资讯:1TB手机干到2599元 手机降价原因找到了:闪存市场暴跌
欧菲光:公司已预约4月28日披露2022年度报告
天天最资讯丨借力函数计算 FC,HEROZ 打造专业级 AI 日本将棋服务
Excelize 发布 2.7.1 版本,Go 语言 Excel 文档基础库
环球今头条!WebAssembly 助力云原生:APISIX 如何借助 Wasm 插件实现扩展功能?
世界速看:记录-html-docs-js避坑指南
阿里正式加入ChatGPT战局,“通义千问”上线后表现如何?
全球消息!债市日报:4月10日
焦点关注:重磅!亚洲最大推力液体火箭发动机试车台调试完成
视焦点讯!堆料最足超大杯!小米13 Ultra确认可变光圈+全焦段四摄
全优大七座SUV!全新一代揽月正式上市 18.99万元起售
环球最新:2人观影全程用手机录制电影内容 目击者:中途还换了一个手机
米哈游《崩坏星穹铁道》姬子角色PV:成熟妩媚的大姐姐
今日快讯:“算力中国行”大型调研采访活动启动,将深入各地了解算力应用发展情况
天天日报丨刷题疑惑3
今日观点!TCP三次握手和四次挥手
【环球报资讯】收评:人工智能板块跳水 10只注册制主板新股大涨
播报:ChatGPT消除无聊的工作 诺奖得主:人类上四休三就靠AI
对标特斯拉Model Y 小鹏G6再放送 博主:兴奋起来吧、有电动尾翼
《名侦探柯南:黑铁的鱼影》新宣传图 成人版灰原哀太劲爆
精彩看点:第三次!沈腾主演《满江红》宣布密钥再次延期:上映至5月15日
亚马逊安抚员工:公司并没有在AI竞争中落下
天天微资讯!私募巨头阿波罗:美国信贷紧缩已开始
全球信息:【AIGC】ChatGPT 相关分享
互联网+医疗|如何满足各项安全合规要求
全球新资讯:一代“金牌配角” 中国香港知名演员吴耀汉去世:终年83岁
世界热消息:单核性能猛增68% 龙芯确认下代CPU性能达市场主流水平
【全球速看料】已做到笔记本电脑大小 国产量子计算机再进化:三大产品升级
环球信息:撞脸苹果!金立发布F1 Plus手机:刘海屏设计 国产8核CPU
《生化危机4:重制版》艾达王配音首次发声:亚裔女演员不止是花瓶