用 netty 写了一个 http & https 代理,在将服务器响应的发送到客户端(浏览器)后,如果不手动关闭代理与服务器的连接以及客户端的连接,netty 就会重用之前的连接,这样的话,整个网站(比如 youtobe )的流量都只通过一个连接通道进行传输,看视频卡得一批。当响应发送到客户端后就关闭 Channel,哇,整个世界都舒服了,网速直接满载,连接的通道也多了,再加上二级代理,youtube 1080p 妥妥的
1
ysc3839 2020-09-09 23:59:55 +08:00 via Android
这是你网络的问题吧?针对单连接进行了限速。如果是 HTTP/2 的话,你这种操作就没用了,一个服务器的所有请求都是使用单个连接的。
|
3
supermoonie OP @ysc3839 限速应该不会有,因为网络在测试期间没有变动,而且测试了很多次。HTTP/2 的话会进行降级处理。单个连接是没问题,如果 keep-alive 的话,新的请求就会使用现有的连接,那么这个连接的传输能力岂不是就会很慢吗?现在通过手动关闭,就有机会创建多个连接,是不是就会快了很多?以上只是猜想,我还需要更多的测试进行验证才能找到问题所在
|
4
supermoonie OP @est 看了下协议的版本,是 HTTP/1.1,应该是 Chrome 对 keep-alive 做了处理,现在就测试的现象来看,主动关闭客户端( Chrome )的通道,网速就上去了,可能是我代理服务器的连接重用机制需要调整,我去查一下 netty 关于连接复用的处理细节再测试看看
|
5
Mohanson 2020-09-10 07:03:54 +08:00 via Android 1
估计你处理完一个 http 请求后没有接着从该 tcp 通道继续读取 http 请求,导致浏览器重用通道后发的请求会喂了狗然后等待几秒时间后重试,和 persistent connection 没关系。另外 http 代理的 persistent connection 在 firefox 上有 bug
|
6
supermoonie OP @Mohanson 应该不是没有继续读取 http 请求的问题,因为 netty 每次的 channelRead 事件,我都有日志打印跟踪,最终都会与服务器的连接通道发出去,还是觉得 Chrome 在处理 keep-alive 的时候,有点迷。如果不主动关闭 Chrome 的 channel,Chrome 就会一直转圈圈,也不会失败,而是等很久才加载出来。现在代理的线程池配置是处理客户端 channel 的固定 16 个线程,处理服务器端 channel 也是固定 16 个线程,所以我在想是不是因为 channel 重用导致线程池被耗尽了
|
7
domosekai 2020-09-10 09:03:45 +08:00
youtube 的视频(googlevideo)本来就是单连接,打开 F12 看看卡在哪儿了
|
8
supermoonie OP @domosekai 卡在了 pending ……
|
9
domosekai 2020-09-10 11:16:29 +08:00 1
pending 表示现有连接被占用,那我的猜测和#5 类似,你的代理因为某种原因让 chrome 无法复用连接,导致卡死超时后再重新连接,虽然你主动断开看上去也可以,但不一定适用于其他网站,我试了下 youtube 的视频在 chrome 使用代理和直连的情况下都是单连接复用
|
10
supermoonie OP @domosekai 待我今天晚上再验证下
|
11
supermoonie OP |
12
arloor 2020-09-10 22:24:45 +08:00
按道理来说,youtube 现在应该是 http2 的了
即使走了 http 代理,也会使用 connect 隧道,在这种情况下,仍然应该是 http2 另外,你的这个项目应该可以在一定程度上对比下这个 https://github.com/arloor/HttpProxy 既然你提到 EmptyLastHttpContent,应该和这个项目的实现差不多 |
13
supermoonie OP @arloor youtube 现在确实是 h2 的协议了,不过代理会对其进行降级,目前还没深入研究,后面再细细研究下 h2 。确实和那个项目差不多,不过我现在写的提供了 HttpRequest 、HttpResponse 的拦截器,动态二级代理支持,黑白名单,远程及本地映射以及即将实现的网络信息统计、自定义 DNS 、限速、vmess 协议、ss 协议等。另外基于拦截器做了一个类似 Charles 的单页面应用,基本上和 Charles 的功能一样,只不过我把请求和响应保存到 sqllite 数据库中了,可以进行查询。另外的打算可能是做插件管理,比如某盘的嗅探多线程下载插件。感觉可以做的很多。。。
|
14
arloor 2020-09-10 23:01:24 +08:00
|
15
supermoonie OP @arloor 现在还没遇到过,等做完了做下各种网络测试。GlobalChannelTrafficShapingHandler 这个 handler 应该能解决很多问题,特别是请求堆积造成的内存泄漏
|
16
monkeyWie 2020-09-11 07:42:08 +08:00 via Android
@supermoonie 跟我这个很像啊,另外还实现了 https 的中间人攻击,https://github.com/monkeyWie/proxyee
|
17
supermoonie OP @monkeyWie 哎呦,大佬大佬,确实是参考了你的那个项目,没想到碰到作者了,只不过我重新写了一遍,加了一些以及需要的功能,另外用 vue 写了一个抓包的界面🤣
|
18
monkeyWie 2020-09-11 09:28:43 +08:00
@supermoonie 哈哈,巧了,抓包最麻烦的地方就是要处理大响应,比如上传文件和下载文件,搞不好就 OOM 了😄
|
19
supermoonie OP @monkeyWie 大的请求和响应,是不是可以通过 Content-Length 判断下,然后超过一定的阈值,先序列化到本地文件中,再通过 Buffer 分块读取,这只是我的猜想,不知道可不可行🤣
|
20
monkeyWie 2020-09-11 10:40:29 +08:00
@supermoonie 我也是这样考虑的,不过 chunked 编码的还要特殊处理下,因为拿不到 Content-Length🤣,还有那个 h2 的如果是 connect 隧道的话应该是不会降级的
|
21
supermoonie OP @monkeyWie 能拿到 FullHttpRequest 以及 FullHttpResponse 中的 content 吧,然后根据这个 content 获取 content-lenght,可还行?等我这周末测试下大的请求 /响应,看看能不能找到解决方法
|