V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  lesismal  ›  全部回复第 52 页 / 共 56 页
回复总数  1101
1 ... 44  45  46  47  48  49  50  51  52  53 ... 56  
2021-02-24 19:22:29 +08:00
回复了 lesismal 创建的主题 分享创造 发布个 golang 高性能异步网络框架 nbio,单击百万不是梦!
@sujin190
兄弟,你这么说是对系统架构的理解有偏差了

基础设施异步不代表业务层也必须异步,比如:
网络层异步,收到数据、decode 后,把 message 丢给业务模块的协程池,业务模块的逻辑还是同步的,需要考虑的是协程池的 size 、避免因为协程池数量平静导致业务阻塞,协程池这个问题在其他基础设施也一样,比如 sql 、redis 的连接池,不够用了该排队等就排队等

golang 给我们了协程,我们不一定只能用协程的同步逻辑
同样道理,其他异步设施,也不是强制你上层必须异步
而是,多种姿势摆在这了,业务层同步还是异步逻辑,你可以自己设计
2021-02-24 17:38:29 +08:00
回复了 lesismal 创建的主题 分享创造 发布个 golang 高性能异步网络框架 nbio,单击百万不是梦!
@byte10 兄弟,java 如果足够好,go 就不会诞生了。。。
go 的协程也不是万能灵药,对于中小项目确实没必要,对于大项目,nio 还是非常有必要的
想象一下,如果你手上大厂某些业务几百甚至几万台硬件,如果 nio,可以节省很多成本,单内存占用就可以省太多太多了
云服务越来越广,高并发相关设施用 go 协程这个成本还是很可观的
2021-02-24 17:35:02 +08:00
回复了 lesismal 创建的主题 分享创造 发布个 golang 高性能异步网络框架 nbio,单击百万不是梦!
@byte10 兄弟,我已经不是少年了。。。本来没想自己撸一套,但是其他那几个,实在不好用
2021-02-24 15:30:52 +08:00
回复了 howellz 创建的主题 Go 编程语言 golang 就没有提供一个可以被 cancel 的 read 接口?
试试我的异步网络库:

https://github.com/lesismal/nbio
2021-02-02 16:31:59 +08:00
回复了 yyyfor 创建的主题 程序员 关于系统瓶颈的面试问题
真热闹,我也补充一些吧

前面的各位都只是说到丢给 redis,但是单就 redis 也有击穿、穿透、雪崩各种说法,1s 几十万全丢给 redis,也只能说各位逮到个好玩意就往死里操,还是太暴力太浪费了

缓存和持久层其实都还是局部性原理的范畴,既然局部性原理,就再进一步,内存缓存,内存缓存这块跟 redis 放一块的话也有多种实现方式,比如:
1. 热点 key 的数据,定时或者发布订阅或者其他什么更新机制,服务节点 load 到自己的内存,请求来了直接返回自己内存缓存的
2. 同 key 访问加锁串行化,上一个请求回来后把结果带回来,其他等待锁的先检查是否有结果了,有了就直接拿结果、不落到 redis 了,相当于合并了到 redis 的请求。这个过程当然也可以结合或者改成内存缓存,比如内存的 1s 过期,内存没有、再 redis 、持久层之类的

高配点的机器,如果不是大 key 、value,几十万 qps 没啥压力,我自己的 i7 PC 测自己的 arpc 都能 40 多万 qps
@guonaihong 好,我 new 个 issue
@guonaihong 你试下我 12 楼和 16 楼的代码,两个 Post,我这里测,只打印了一组 begin/complete,不知道是不是我测试代码写错了,如果写错了楼主给指正下我再试试,如果没写错应该算是丢了个请求
上一楼打错字,"第二次发剩下的 1.5" 应该是 "第二次发剩下的 0.5"
@guonaihong 楼主先淡定点,不是开火的意思

我说没返回是指标准库返回了完整的 Request 结构体,Request 内已经把 URL/Header 各字段之类的解析好了,楼主的 httpparser 虽然 setting 里可以设置回调,但也是业务层自己需要二次加工,如果是对比性能,标准库相当于比你默认的 bench 代码多做了每个字段的解析,这样 bench 对比对标准库是不公平的

另外 1.5 个包的问题,比如我在 12 楼的测试代码,两个 http post 的数据,第一次发 1.5 个,第二次发剩下的 1.5,比如 setting 的回调这样:
var setting = httparser.Setting{
MessageBegin: func() {
fmt.Println("---- begin")
},
HeadersComplete: func() {
fmt.Println("---- complete")
},
}

只打印了一组
---- begin
---- complete

我没有去做更完整的测试和调试、不敢确定,提出来你看下算不算 bug,如果我看错了你解释就好了

技术交流,心态平和,需要豁达,不要火大 ^_^
只是解析出一个个包、不解析包内各段落具体字段相对简单,但是对实际工程帮助也不大,所以离工程使用还有很长距离
我尝试了上一楼的 1.5 个包,没法返回单个包给业务层。算是 bug
@guonaihong “设计的时候支持分段传入,内部是一个状态机。”—— 试一下一次读 1.5 个包的内容

var data = []byte(
"POST /joyent/http-parser HTTP/1.1\r\n" +
"Host: github.com\r\n" +
"DNT: 1\r\n" +
"Accept-Encoding: gzip, deflate, sdch\r\n" +
"Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4\r\n" +
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) " +
"AppleWebKit/537.36 (KHTML, like Gecko) " +
"Chrome/39.0.2171.65 Safari/537.36\r\n" +
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9," +
"image/webp,*/*;q=0.8\r\n" +
"Referer: https://github.com/joyent/http-parser\r\n" +
"Connection: keep-alive\r\n" +
"Transfer-Encoding: chunked\r\n" +
"Cache-Control: max-age=0\r\n\r\nb\r\nhello world\r\n0\r\n" +

"POST /joyent/http-parser HTTP/1.1\r\n" +
"Host: github.com\r\n" +
"DNT: 1\r\n" +
"Accept-Encoding: gzip, deflate, sdch\r\n" +
"Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4\r\n" +
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) " +
"AppleWebKit/537.36 (KHTML, like Gecko) " +
"Chrome/39.0.2171.65 Safari/537.36\r\n" +
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9," +
"image/webp,*/*;q=0.8\r\n" +
"Referer: https://github.com/joyent/http-parser\r\n" +
"Connection: keep-alive\r\n" +
"Transfer-Encoding: chunked\r\n" +
"Cache-Control: max-age=0\r\n\r\nb\r\nhello world\r\n0\r\n")

p := httparser.New( httparser.REQUEST)
fmt.Printf("req_len=%d\n", len(data)/2)
data1, data2 := data[:600], data[600:]
sucess, err := p.Execute(&setting, data1)
if err != nil {
panic(err.Error())
}
if sucess != len(data1) {
panic(fmt.Sprintf("sucess 111 length size:%d", sucess))
}

sucess, err = p.Execute(&setting, data2)
if err != nil {
panic(err.Error())
}
if sucess != len(data2) {
panic(fmt.Sprintf("sucess 222 length size:%d", sucess))
}

p.Reset()
@guonaihong "标准库的 http.ReadRequest,每秒只能处理 124MB 。相比之下 httparser 可以 300MB,性能还是可以的。" —— 这么说不太公平,标准库的是返回了 Request 、url header body 各段落字段都做了解析的
还想要 TLS 之类的支持,都搞细搞全了,也是个大工程。。。
我之前也想写一份 httpparser 来着,细想了下,没时间,放弃了。。。
大概看了下,不确定是否准确:
1. "粘包"可能有问题,不只是一个包可能拆成多段被应用层分多次读取到,也可能是多个包的数据放一块、被应用层从任意中间位置分多次读取到,比如 3 个包被两次读到、两次分别读到前 1.5 个和后 1.5 个包
2. 好像只是解析一个完整包的功能,并没有返回一个 Request/Response 类似的结构,所以 header 、body 之类的还是要业务层自己解析一道,这样的话业务层仍需要重复解析一次长度相关、比较浪费

建议也解析 header 、body 相关内容,一个完整包解析完之后返回一个 Request/Response 给业务层处理,在这基础之上 parser 内置 buf 的缓存,一个段落或者一个完整包后剩余的 half 部分由 parse 自己存上,有新数据来了加一块继续解析,这样业务层不必通过 success 再截断数据跟下次数据放一块,也免去重复解析 half 的浪费
2021-01-29 12:23:56 +08:00
回复了 fewuliu 创建的主题 Vue.js 尤雨溪承认 Vite 在之后会取代 Vue CLI,你开始学 Vite 了吗?
原生 js 足够用,只是以前的大多数前端工程师们缺乏工程性系统性思考。工程管理、性能优化,试试我这个:

https://www.v2ex.com/t/747412#reply8

https://www.v2ex.com/t/743590#reply20
端口数量通常不是问题,文件描述符上限设置个 10w 、100w,其他的几个内核参数设置合理就行,只要你硬件配置足够。不过还真有的站点设置的不合理,golang 中国报错文件打开数量过多我就遇到过好多次。socket 是 4 元组,单 IP 自己过来的最大端口 65535,不代表服务器对所有 IP 加起来只能 65535,而且单 IP 除非故意写 bug 或者攻击、否则也不至于有这么多,而且这些 CDN 、防火墙那里就能挡,还轮不到业务层来处理这个(并且业务曾代码也没有这个能力处理)

如果是觉得某个设备只要超过两三个连接就算过多,那就看我上一楼说过,限制机制自己订制下就好
另外,怕连接数过多的话,单节点配置好最大在线数,新连接进来的时候判断下、超过了就拒绝掉,这个可以在网关或者业务节点的 upgrader checkorigion 里做,更好点的方式是自己 wrap 下 net.Listener,serve(listener),Accept 的地方直接做
节点数不多、redis 的话,每个节点每秒 hset 、hmget 下就行了,没啥压力,而且实时性也足够
BTW,我这有个 ARPC 的 golang 框架提供了 websocket 聊天的简单示例

https://github.com/lesismal/arpc/tree/master/examples/webchat

另外 ARPC 支持发布订阅,如果想自己实现个管理服务器进行多个服务节点的在线数统计,管理服务器接收上报人数、然后把多节点的业务服在线总和发布就行了

想简单处理的话轮询写、读 redis 就好了
1 ... 44  45  46  47  48  49  50  51  52  53 ... 56  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2889 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 30ms · UTC 13:11 · PVG 21:11 · LAX 06:11 · JFK 09:11
Developed with CodeLauncher
♥ Do have faith in what you're doing.