V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  lesismal  ›  全部回复第 25 页 / 共 60 页
回复总数  1185
1 ... 21  22  23  24  25  26  27  28  29  30 ... 60  
#17 go 性能、占用、开发效率能达到非常好的平衡。自定制起来也比 nginx lua/resty 要更有潜力。
@0o0O0o0O0o
其实用 go 最大的好处是:可以省去 nginx 了。:joy:
@lesismal #14

> 或者 OP 也可以另一种方案,还是先自己封装下 Listener ,tls Accept 得到的 tls Conn 用 RemoteAddr string 存 map 里

ConnContext 就可以了,更简单
@0o0O0o0O0o SaveConnInContext 这个挺好,学到了

@dzdh 要不我把 nbio 的 tls 的 clientHello 以及 clientHello 的 marshal 暴露出来,然后就方便拿到了,我本地改了试了下是可以的了,暂时没有更新到 repo:
https://gist.github.com/lesismal/316b711a7f39cc539cebaad6c8e5b0fd?permalink_comment_id=4545513#gistcomment-4545513



但是 nbio 只支持 http1.x ,http2.0/3.0QUIC 功能太多、我短期内没精力去做了。

或者 OP 也可以另一种方案,还是先自己封装下 Listener ,tls Accept 得到的 tls Conn 用 RemoteAddr string 存 map 里,handler 里取出 tls Conn ,并且反射或者自己 type 一个相同 fields 的结构体但是 ClientHello 大写导出的方式+unsafe 指针强转类型后把 clientHello 这个字段取出来用,但是这样怕 go 不同版本该结构体字段发生变化,要自己额外做一些对应 go 不同版本编译的兼容
#8

修改了下,用标准库的没必要自己封装 Listener ,直接 ConnState 处理就可以了,代码更新了

```golang
package main

import (
"context"
"fmt"
"net"
"net/http"
"os"
"os/signal"
"sync"
"time"

"github.com/lesismal/nbio/nbhttp"
)

var connections = sync.Map{}

func nbioOnEcho(w http.ResponseWriter, r *http.Request) {
res, ok := w.(*nbhttp.Response)
if ok {
conn := res.Parser.Processor.Conn()
yourData, ok := connections.Load(conn)
if ok {
fmt.Println("nbioServer onEcho:", yourData)
} else {
fmt.Println("nbioServer onEcho: not found connection")
}
}
w.Write([]byte(time.Now().Format("20060102 15:04:05")))
}

func nbioServer() {
mux := &http.ServeMux{}
mux.HandleFunc("/", nbioOnEcho)

engine := nbhttp.NewServer(nbhttp.Config{
Network: "tcp",
Addrs: []string{"localhost:8080"},
Handler: mux,
IOMod: nbhttp.IOModBlocking,
})
engine.OnOpen(func(conn net.Conn) {
fmt.Println("nbioServer onOpen:", conn.RemoteAddr())
yourData := "data: " + conn.RemoteAddr().String() // or other things
connections.Store(conn, yourData)
})
engine.OnClose(func(conn net.Conn, err error) {
connections.Delete(conn)
fmt.Println("nbioServer onClose:", conn.RemoteAddr(), err)
})

err := engine.Start()
if err != nil {
fmt.Printf("nbio.Start failed: %v\n", err)
return
}

interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)
<-interrupt

ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
defer cancel()
engine.Shutdown(ctx)
}

func netOnEcho(w http.ResponseWriter, r *http.Request) {
yourData, ok := connections.Load(r.RemoteAddr)
if ok {
fmt.Println("netServer onEcho:", yourData)
} else {
fmt.Println("netServer onEcho: not found connection " + r.RemoteAddr)
}
w.Write([]byte(time.Now().Format("20060102 15:04:05")))
}

func netServer() {
mux := &http.ServeMux{}
mux.HandleFunc("/", netOnEcho)

server := &http.Server{
Addr: "localhost:8080",
Handler: mux,
ConnState: func(conn net.Conn, state http.ConnState) {
switch state {

case http.StateNew:
fmt.Println("netServer onOpen:", conn.RemoteAddr())
remoteAddr := conn.RemoteAddr().String()
yourData := "data: " + remoteAddr // or other things
connections.Store(remoteAddr, yourData)
case http.StateActive:
case http.StateIdle:
case http.StateHijacked:
case http.StateClosed:
connections.Delete(conn)
fmt.Println("netServer onClose:", conn.RemoteAddr())
}
},
}
err := server.ListenAndServe()
fmt.Println("server exit:", err)
}

func main() {
netServer()
// nbioServer()
}
```
哦对了,基于标准库的代码部分,我忘记处理连接关闭时 Map.Delete 了,得看下 ConnState 之类的 Hook 能不能处理,如果不能处理,那基于标准库还不能这样简单搞、连接断开不清理就相当于泄露了导致 map 无限增长
如果只是要知道 ip 相关,使用 RemoteAddr 就可以了。

如果是需要其他信息(但楼主不讲明是需要什么的前提下我还真想不出 conn 除了 remote addr 还需要啥信息这么有必要去特殊处理),基于标准库包装一下 Listener 自己 map 映射存上也可以,或者基于 nbio OnOpen 。

基于标准库和 nbio 的区别是:
基于标准库的方式在 handler 里没法拿到 Conn ,因为只有 Hijack 一种方法拿到,但拿到后标准库 http server 就不继续处理该 Conn 了、Hijack 得到的 Conn 处理权转给了用户;
nbio 的 http handler 里除了 Hijack 的方式、也可以通过类型断言拿到 Conn 并且不涉及处理权的转移。

完整代码:
https://gist.github.com/lesismal/316b711a7f39cc539cebaad6c8e5b0fd

代码只示例了 4 层的 Conn ,如果需要 tls ,另外再加点处理、OP 可以自行探索
2023-04-18 19:23:47 +08:00
回复了 Xyg12133617 创建的主题 问与答 女友五一要去见前男友,我有点不想坚持了
2023-04-18 14:19:35 +08:00
回复了 yingzijiejie 创建的主题 Python 关于《流畅的 Python (第 2 版)》一书的用纸
我来支持下 OP ,我个人是不反感这种纸张的。
记忆里电力、机械工业等其他出版社的计算机类书籍,也不少这种薄纸。好几年没看纸质书、好些都送给朋友了,《深入理解 linux 内核》《 linux 设备驱动程序》《算法导论》。。。记不清楚是哪些书比较透了,印象最深的好像 O'Reilly 的不少中文版都是这样,很像 uni*/linux ,实而不华。
印象里纸张比较好的要属《 Unix 环境高级编程》,但确实厚重,如果可以选,我希望它薄一点,透不透我倒是不觉得影响阅读。
2023-04-18 14:04:25 +08:00
回复了 lesismal 创建的主题 Go 编程语言 nbio 近期的一些功能更新,来骗点 star
@blackvv666 感谢支持,欢迎交流,有建议、疑问、bug 之类的随时来 issue
@icyalala
对,大家基本观点是一致的。

string 在传统语言里的设计也是不太友好,支持二进制通用才更舒服,但也确实省了一点标识头。

capnproto 好久以前看到官方自己的数据非常牛,但这个我一直没在自己项目里用过,你们实际项目有用到不?好用不?
2023-04-17 17:35:07 +08:00
回复了 chai2010 创建的主题 程序员 凹语言中文语法设计
@pkwenda 不过文坛马上就是 AI 的天下了,所以损失了也无所谓:dog:
@Nazz 你没看懂我意思,我说的不是现有的 MessagePack 实现性能有优势

#51
但是单就性能而言,这里还是有个市场占有率的问题。因为 MessagePack 用户没那么多、像 #45 @hengyunabc 所说的,作者也没那么大精力和动力去做更大的性能优化。如果很多很多人用,MessagePack 的性能应该是可以做到比 simdjson 更强的,因为需要处理的字节数、逻辑肯定是比 json 少一点的,simd 指令能用来优化优化 json 也可以用于 MessagePack ,比如 simdjson 作者去实现 MessagePack 。
2023-04-17 15:31:10 +08:00
回复了 justincnn 创建的主题 Android 大家在安卓上用什么 todo list 的工具?
github issue
2023-04-17 15:30:43 +08:00
回复了 chai2010 创建的主题 程序员 凹语言中文语法设计
我只想说,OP 精力花在凹语言上,是 gopher 社区的损失。
2023-04-17 15:27:03 +08:00
回复了 zhangolve 创建的主题 程序员 大佬的起诉书公布了大佬的工资待遇
@trlove 看到#78 里的 1800w 我没看懂,看到#79 的 700 多 w ,我还是没看懂,其他楼层都说是 150 ,700 多是怎么算出来的:joy:。。。
上一楼手滑发布了,接#52

SIMD 的优点?我们普通应用场景中有很多情况下需要对大量数据执行相同的操作,例如图片处理、视频特效等,在这种时候使用 SIMD 指令能取得很大的性能提升。例如 SSE 指令,支持每次对 4 个 FP32 进行操作,那么我们常用的 Vector4 向量加减乘除,皆可使用一个指令完成,效率大大提高。

SIMD 的缺点?有得必有失,为 SIMD 优化的程序在处理分支指令时性能不佳,因为分支指令本质上是一部分数据流根据条件去执行不同的指令,当多个数据流需要运行的分支不同时,需要运行两次程序遍历来完成所有数据流的操作。此外,不是所有情况下都需要很高的并行度,典型例子就是 AVX512 指令。虽然理论上一次能处理 16 个 FP32 ,但很难遇到需要同时处理这么多数据的场景。常见的向量、矩阵计算,操作单位都是 Vector4 ,要适配 AVX512 就需要大改程序流程和算法,去把好几个数凑起来一起操作,边际效应明显。而且在前几代 CPU 上 AVX512 还有降频问题,一跑起来频率上不去,速度还不一定有 SSE 快。

所以,常规主流业务的普通 size 结构场景下,simd 是否还有优势?

3. simdjson 和 MessagePack c 编译优化是如何的,比如都是 O1 还是 O2 还是 O3 ,实际场景允许到 O3 不?
@icyalala
> 体积:相差并不大
> json: 467KB
> msgpack: 402KB
> 在手头 M1 上跑 simdjson 和 msgpack-c 来解析,循环 16 次
> simd:dom: 759MB/s
> simd:ondemand: 1604MB/s
> msgpack-c: 948MB/s

另外,这种性能对比是存在一些不合理的:
1. 是应该对比相同结构的序列化反序列化次数,而不是对比每秒处理了多少 MB/GB
2. 这种 size 的结构已经是非常大了,实际的业务中,单个消息体这么大的时候应该是少数场景。所以也应该考虑常规 size 的结构的压测对比,我对 simd 指令没做过什么研究,随便搜了一段:
@icyalala
我不是挺 MessagePack ,我自己主业务也基本不用它。
但是单就性能而言,这里还是有个市场占有率的问题。因为 MessagePack 用户没那么多、像 #45 @hengyunabc 所说的,作者也没那么大精力和动力去做更大的性能优化。如果很多很多人用,MessagePack 的性能应该是可以做到比 simdjson 更强的,因为需要处理的字节数、逻辑肯定是比 json 少一点的,simd 指令能用来优化优化 json 也可以用于 MessagePack ,比如 simdjson 作者去实现 MessagePack 。

> 也没验证 UTF-8 编码

MessagePack 本来就是二进制,当然是不需要验证 utf8 的,主要还是 simd 针对性优化太强。


@duke807
> 至于其它通讯格式,我当然知道它们的存在,我也知道它们是怎么死的,我一开始就不看好它们,无论是 xml 还是 protobuf

xml 没死,protobuf 更是没死,只是 web 领域用的人少罢了。大规模服务集群之间的 RPC ,pb 占有率还是很高的,游戏行业 pb 的占有率也非常高。


一些传统 c/cpp 领域,不涉及深拷贝的,就是 c struct 1 字节对齐,直接 struct 地址拷贝传输,性能和 buffer size 都是无敌的。

二位没必要争执这些,http1x 性能和流量浪费都那么垃圾也照样统治着互联网。技术栈的市占率都是历史综合因素造成的,自己家的业务选择自己认为适合的、自己喜欢的就行了。
2023-04-16 13:33:28 +08:00
回复了 Nazz 创建的主题 程序员 有必要在海量长连接场景使用第三方网络库吗?
@Nazz 还没试过,尝试这个要改造的工作量也不小
1 ... 21  22  23  24  25  26  27  28  29  30 ... 60  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2959 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 40ms · UTC 02:48 · PVG 10:48 · LAX 18:48 · JFK 21:48
Developed with CodeLauncher
♥ Do have faith in what you're doing.