补充测试了一下,单线程也这个样子。性能差到令人难以理解,为了避免主线程负载问题,我已经特意设置了下载限速 2MB/s,而且看起来主线程也没什么负载。
界面卡顿已经是老毛病了,,,卡习惯了表示1秒一卡界面刷新已经觉得算不卡能接受了
只能说把boost的context,还有jemalloc内存优化都用上看看能不能提高性能
比特彗星运行上万个任务的也大有人在,,,能接受卡顿就对了,至少比qb多任务运行来的流畅
就好比,,,上面的,一个JSON把程序干崩溃,估计都不太好找到问题在哪怎么修复
我基本每台种子服务器控制在1000个文件内,目前170ms左右响应api,文件数越多就越卡,文件数少就响应快,估计也就是api响应慢了就导致界面进入锁等待,收到数据后才刷新一下,产生界面卡顿的假象
不知道还有什么好办法分析进程卡顿占用,比如说Windbg找函数?
linux倒是方便直接gdb就完事了
还是说ProcDump,procdump -mp -e -w bf4.exe
界面卡顿已经是老毛病了,,,卡习惯了表示1秒一卡界面刷新已经觉得算不卡能接受了
我这里测试界面是不卡顿的,但是 WebAPI 请求一次要接近 4 秒钟,这就不行了。
BitComet 的 API 设计决定了我要为每个种子都请求一次详细信息,如果说你有 5w 个种子,显然就要请求 10w+1 次(1 次任务列表,N次任务详情,N次 Peers 列表)。
现在别说 5w 了,50 个就已经趴窝了。这也不是什么内存分配问题,单纯感觉是有什么东西写糊了。
比特彗星运行上万个任务的也大有人在,,,能接受卡顿就对了,至少比qb多任务运行来的流畅
qb 的老问题了,但其实还凑合。可以看看隔壁 BiglyBT,只要内存管够,满足你的一切想象。
就好比,,,上面的,一个JSON把程序干崩溃,估计都不太好找到问题在哪怎么修复
内存爆掉可能是最好找原因的了……如你所见,拉一份 heapdump 就能看到问题所在。新版本 BitComet 可以指定只获取我需要的,现在内存情况好多了。然而,这并不能解决 WebAPI 令人裂开的性能问题。
不知道还有什么好办法分析进程卡顿占用,比如说Windbg找函数?
找函数不好用,我 IDA 试过了,BitComet 把符号都擦干净了。对着内存地址看不出来半点有用的信息,至少我不行。
linux倒是方便直接gdb就完事了
我不觉得没有符号的情况下,gdb 能比 windbg 好用。
题外话:qBittorrent 的 WebAPI 设计好多了,在一次请求里面就能拿够所有的信息。
qBittorrent 我需要请求 N+1 次:1 次任务列表 + N 次 Peers 列表
BitComet 我需要请求 2N+1 次:1 次任务列表 + N 次任务详情 + N 次 Peers 列表
说实话,给 BitComet 做第三方相当痛苦。BitComet 是个闭源软件我完全可以理解。但 WebAPI 时时刻刻都在修改。有的修改完全不会反映到 changelog 上。
举个例子,Peers 结构体的 group 字段,短短两个 minor 版本,做出了四次修改:
无 → connected
→ connected_peers
→ peers_connected
。这些修改都是舞台背后修改的,没有任何发行注记提示字段被修改。都是用户反馈功能失效后我才发现被更改了。我对修改接口没有意见,必要的修改是应该修改的,但是就这三次变化来看,我觉得并不是特别有必要。
再举个例子: IP 过滤器的接口,过去几个版本也得到了多次更新。
enable_ipfilter
→ enable_ip_filter
enable_whitelist_mode
从 true/false 换成了 ipfilter_mode
blacklist/whitelist
这些非关键字段更新都破坏了相当多的逻辑,我不得不给它们单独编写代码去做兼容。
说点别的:
有一点我也想说很久了,小樱一直在谈及 BitComet 非常优秀,然后批评 qBittorrent 很多点。
我承认 qBittorrent 有很多不足(稳定性、BUG、内存泄露),也承认 BitComet 有很多优秀之处(LTSeed,大量种子的性能等等)。
但是就我最近一个月接触 BitComet 来说,BitComet 真的算不上特别优秀。给 BitComet 的 WebAPI 编写代码是一件相当痛苦的事,我可以说目前我还在努力的兼容 BitComet 完全是因为用户的需要。
我在给 BitComet 编写兼容支持部分的时候,时间大多数都浪费在了一些不那么重要的地方:
- 最开始的时候,研究登录加密算法;我花了两天最后还是在群友逆向的帮助下找到了正确的加密算法
- 接下来的时间,和 WebAPI 斗智斗勇;缺少公开的文档意味着我只能抓 WebUI 的请求和读编译后的可读性很差的 JS 文件来搞清楚 WebAPI 该如何使用和请求
- 维护期间,基本是在反复的做回归测试,因为我完全不知道是不是有端点的请求参数或者响应被修改了
- 因为 WebAPI 还不成熟,出现了问题我只能每天来论坛反馈,不过好在 BitComet 修得非常及时,这一点上 BitComet 超越了其它大部分的软件
我的用户群里各种软件的用户都有,已经有很多次有人截图找我说说小樱有些 “拉踩 qBittorrent”,你怎么和Ta还在合作?
不过我个人并不在乎。每个软件都有其优点和缺点,我各种 BT 软件都用,以应对不同的场景。但说实话,每次看到 qBittorrent 被冠上吸血之名时,我个人还是很难受的。如果 qBittorrent 不再吸血,我可能就不会被上门查水表,也不用签保证书,不用被限速也不用被拍照,也可能不用去做 PBH 这类软件了。
它的默认参数可能不够 Pro,但是作为相当大用户量的软件,它需要考虑到大多数用户的情况。在 BT 网络互相分享的情况下,默认上传槽位其实相当够用。目前看着如此吸血的主要原因是,qbt 宝贵的 upload slot 都被吸血 peer 占用,而它们又不给别人上传。
连接数这些限制也不是越多越好,我完全理解 qbt 的默认设置。如果你用的网络设备不够好,很容易造成断网断流。我在使用之前 zmx 论坛的优化版本的 BitComet 时,因为笔记本连接的 WIFI,当场就干停了我宿舍的路由器。考虑到有如此多的人都有这个问题,这只能证明这并不是一个对大多数人都有好的默认参数。
说回 API 问题:
Azureus/Vuze/BiglyBT 和 Deluge 的 WebUI 尽管很差,但它们支持插件,我们自己编写适配器,完全满足了所有要求,同时性能也不错
qBittorrent 不如前者灵活,但优秀的 WebAPI 设计和良好的性能也还算好,功能也算够用;一套并发干下去也不喘气,所以也没问题
BitComet 在这方面还有相当长的一段路要走,不管是 API 设计还是性能,都不能算是很好,只能是够验证理论,看起来能用。我基本最近一个月都在处理 BitComet 的支持请求,只能不厌其烦的告诉用户 “这个问题已经向 BitComet 反馈过了,这个问题超出了我的解决范围,我对此无能为力,静待版本更新吧”
结尾:
抱歉说了这么多,有的时候晚上确实会思考很多。不针对任何人,也不针对 BitComet —— 我希望大家都平等的看待不同的软件,都是正儿八经的 BT 软件,不要搞出来鄙视链。
不同的场景,不同的用户,不同的使用习惯适合不同的软件。
- 跑 PT 的选手,喜欢抢流量,它们用 qBittorrent 下载速度更快,有机会抢到更多的上传,昼夜不停。
- 保种的选手,希望尽可能低的资源占用,所以对小巧的 Transmission 爱不释手。
- 我的老父亲,多年的网民,年轻时用电驴,现在不跑 ed2k 了,只跑 BT,喜欢用 BitComet,因为配置简单,简洁直观。对他来说,他的需求就是下个大片电影看看,做做种就关机了。
- 我的室友,BT/PT 都玩,对他来说 qBittorrent 足够好用
- 普通的群友,只是希望下载磁力,他也不想学习什么做种保种,他只想下载到资源,所以用的迅雷
- 而我,更喜欢 BiglyBT,控制更自由,细节更多,信息更多
所以真的没有什么谁最好,谁最垃圾;场景不同,用户不同,需求不同。每个人都会做出最适合自己的选择。何必每天打客户端之战呢?
说实话我这边没跑过并发访问webui api的测试,你这边的应用场景我得专门想办法模拟一下。有简化版的测试客户端的话,可以私信给我测试一下?
你需要什么样的api接口,可以直接写出来。我现在的接口都是为webui设计的,想必不适合直接适配你的需求
论坛里发布的都是测试版,接口参数肯定不稳定,随着webui界面调整会不断优化。你如果需要跟踪接口的最新变化,可以私信我,毕竟接口细节不适合直接在论坛帖子里公开
最后,感谢你花了大量时间做适配。如果需要提高沟通效率,欢迎私信我
我后续测试了一下,即使不使用并发,单线程请求,在有多个任务同时活动下载的时候,平均请求耗时会快速上涨,接近每个请求 4 秒。多个任务的情况下,会导致无法在合理时间内完成所有请求。
如果我停止所有的任务,这个耗时会立刻下降到合理区间,以相当快的速度完成响应。
这个问题我在 2.10测试版 - #112 2908803755 这里提到过,但随着最近的版本更新,性能似乎越来越糟糕了。
能把任务详情 /api/task/summary/get
的数据拉平到 /api_v2/task_list/get
就好,这对 WebUI 也有好处,避免了浏览器发起大量的请求,并可以显示足够多的基本信息。
这是 qbittorrent 的响应,提供的数据恰到好处:
"c15e9b4ed3d8410b2dc479a7d74916bc6233eab0": {
"added_on": 1728112882,
"amount_left": 0,
"auto_tmm": false,
"availability": -1,
"category": "",
"comment": "",
"completed": 5287520256,
"completion_on": 1728112892,
"content_path": "E:\\Download\\zh-cn_windows_11_enterprise_ltsc_2024_x64_dvd_cff9cd2d.iso",
"dl_limit": 0,
"dlspeed": 0,
"download_path": "",
"downloaded": 0,
"downloaded_session": 0,
"eta": 8640000,
"f_l_piece_prio": false,
"force_start": false,
"has_metadata": true,
"inactive_seeding_time_limit": -2,
"infohash_v1": "b84e74c1dbcc88a02c5b24a6f84383f353a2e1dd",
"infohash_v2": "c15e9b4ed3d8410b2dc479a7d74916bc6233eab0497c29b7e1c58cc9e10f54b0",
"last_activity": 1729172163,
"magnet_uri": "magnet:?xt=urn:btih:b84e74c1dbcc88a02c5b24a6f84383f353a2e1dd&xt=urn:btmh:1220c15e9b4ed3d8410b2dc479a7d74916bc6233eab0497c29b7e1c58cc9e10f54b0&dn=zh-cn_windows_11_enterprise_ltsc_2024_x64_dvd_cff9cd2d.iso&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&tr=udp%3A%2F%2Fopen.tracker.cl%3A1337%2Fannounce&tr=udp%3A%2F%2Fopen.demonii.com%3A1337%2Fannounce&tr=udp%3A%2F%2Fopen.stealth.si%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.torrent.eu.org%3A451%2Fannounce&tr=udp%3A%2F%2Fexodus.desync.com%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.theoks.net%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker-udp.gbitt.info%3A80%2Fannounce&tr=udp%3A%2F%2Fexplodie.org%3A6969%2Fannounce&tr=https%3A%2F%2Ftracker.tamersunion.org%3A443%2Fannounce&tr=udp%3A%2F%2Ftracker2.dler.org%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker1.myporn.club%3A9337%2Fannounce&tr=udp%3A%2F%2Ftracker.tiny-vps.com%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.dler.org%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.bittor.pw%3A1337%2Fannounce&tr=udp%3A%2F%2Ftracker.0x7c0.com%3A6969%2Fannounce&tr=udp%3A%2F%2Fretracker01-msk-virt.corbina.net%3A80%2Fannounce&tr=udp%3A%2F%2Fopentracker.io%3A6969%2Fannounce&tr=udp%3A%2F%2Fopen.free-tracker.ga%3A6969%2Fannounce&tr=udp%3A%2F%2Fnew-line.net%3A6969%2Fannounce",
"max_inactive_seeding_time": -1,
"max_ratio": 1.5,
"max_seeding_time": -1,
"name": "zh-cn_windows_11_enterprise_ltsc_2024_x64_dvd_cff9cd2d.iso",
"num_complete": 71,
"num_incomplete": 80,
"num_leechs": 0,
"num_seeds": 0,
"popularity": 27.251718417546623,
"priority": 0,
"private": false,
"progress": 1,
"ratio": 0.22004520165756883,
"ratio_limit": -2,
"reannounce": 5,
"root_path": "",
"save_path": "E:\\Download",
"seeding_time": 21235,
"seeding_time_limit": -2,
"seen_complete": 1729171677,
"seq_dl": false,
"size": 5287520256,
"state": "stalledUP",
"super_seeding": false,
"tags": "",
"time_active": 21234,
"total_size": 5287520256,
"tracker": "udp://tracker.dler.org:6969/announce",
"trackers_count": 20,
"up_limit": 0,
"uploaded": 1163493461,
"uploaded_session": 0,
"upspeed": 0
}
如果需要模拟测试,这里有一段示例代码:
@Override
public List<Torrent> getTorrents() {
Map<String, String> requirements = new HashMap<>(); // 配置基本参数
requirements.put("group_state", "ACTIVE");
requirements.put("sort_key", "");
requirements.put("sort_order", "unsorted");
HttpResponse<String> request;
try {
request = httpClient.send(
MutableRequest.POST(apiEndpoint + BCEndpoint.GET_TASK_LIST.getEndpoint(),
HttpRequest.BodyPublishers.ofString(JsonUtil.standard().toJson(requirements)))
.header("Authorization", "Bearer " + this.deviceToken)
, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); // 获取任务列表
} catch (Exception e) {
throw new IllegalStateException(e);
}
if (request.statusCode() != 200) {
throw new IllegalStateException(tlUI(Lang.DOWNLOADER_BC_FAILED_REQUEST_TORRENT_LIST, request.statusCode(), request.body()));
}
var response = JsonUtil.standard().fromJson(request.body(), BCTaskListResponse.class);
Semaphore semaphore = new Semaphore(16); // 16 线程并发,但测试过程中发现,不管并发调多大,WebAPI 的性能都很糟糕,任务一多就非常慢,所以并发一点用都没有
List<BCTaskTorrentResponse> torrentResponses = Collections.synchronizedList(new ArrayList<>(response.getTasks().size()));
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
response.getTasks().stream().filter(t -> t.getType().equals("BT")) // 过滤只看 BT 任务,忽略 HTTP 等
.forEach(torrent -> executor.submit(() -> { // 刷取每个任务的任务详情,因为仅仅获取任务列表,得到的数据和信息并不足够,这些额外的请求在任务较多的时候会显著延长耗时
try {
semaphore.acquire();
Map<String, String> taskIds = new HashMap<>();
taskIds.put("task_id", torrent.getTaskId().toString());
HttpResponse<String> fetch = httpClient.send(MutableRequest.POST(apiEndpoint + BCEndpoint.GET_TASK_SUMMARY.getEndpoint(), HttpRequest.BodyPublishers.ofString(JsonUtil.standard().toJson(taskIds)))
.header("Authorization", "Bearer " + this.deviceToken),
HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); // 请求 /api/task/summary/get 端点,卡住的问题也就发生在这里
System.out.println(System.currentTimeMillis() + " Received a RESP");
var torrentResp = JsonUtil.standard().fromJson(fetch.body(), BCTaskTorrentResponse.class);
torrentResponses.add(torrentResp);
} catch (IOException | InterruptedException e) {
log.warn(tlUI(Lang.DOWNLOADER_BITCOMET_UNABLE_FETCH_TASK_SUMMARY), e);
} finally {
semaphore.release();
}
}));
}
return torrentResponses.stream().map(torrent -> new TorrentImpl(torrent.getTask().getTaskId().toString(),
torrent.getTask().getTaskName(),
torrent.getTaskDetail().getInfohash() != null ? torrent.getTaskDetail().getInfohash() : torrent.getTaskDetail().getInfohashV2(),
torrent.getTaskDetail().getTotalSize(),
torrent.getTaskStatus().getDownloadPermillage() / 1000.0d,
torrent.getTask().getUploadRate(),
torrent.getTask().getDownloadRate(),
torrent.getTaskDetail().getTorrentPrivate()
)).collect(Collectors.toList());
}
在获取完上面的任务列表和任务详情后,需为每个种子都获取一次 Peers,这一部分耗时似乎还行,考虑到大部分下载器都需要单独调用,这里可以不做修改:
@Override
public List<Peer> getPeers(Torrent torrent) {
HttpResponse<String> resp;
try {
Map<String, Object> requirements = new HashMap<>();
requirements.put("groups", List.of("peers_connected")); // 2.11 Beta 3 可以限制获取哪一类 Peers,注意下面仍需要检查,因为旧版本不支持
requirements.put("task_id", torrent.getId());
requirements.put("max_count", String.valueOf(Integer.MAX_VALUE)); // 获取全量列表,因为我们需要检查所有 Peers
resp = httpClient.send(MutableRequest.POST(apiEndpoint + BCEndpoint.GET_TASK_PEERS.getEndpoint(),
HttpRequest.BodyPublishers.ofString(JsonUtil.standard().toJson(requirements)))
.header("Authorization", "Bearer " + this.deviceToken),
HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
} catch (Exception e) {
throw new IllegalStateException(e);
}
if (resp.statusCode() != 200) {
throw new IllegalStateException(tlUI(Lang.DOWNLOADER_BC_FAILED_REQUEST_PEERS_LIST_IN_TORRENT, resp.statusCode(), resp.body()));
}
var peers = JsonUtil.standard().fromJson(resp.body(), BCTaskPeersResponse.class);
//noinspection UnusedAssignment
resp = null; // 立即手动释放 resp 的对象引用,部分版本 BitComet 一个响应能高达 12 MB,考虑到 PBH 的设计运行内存上限仅 386MB ,所以辅助 GC 完成垃圾回收是值得的。
if (peers.getPeers() == null) {
return Collections.emptyList();
}
var noGroupField = peers.getPeers().stream().noneMatch(dto -> dto.getGroup() != null); // 2.10 的一些版本没有 group 字段
var stream = peers.getPeers().stream();
if (!noGroupField) { // 对于 2.10+ 新版本,添加一个 group 过滤
stream = stream.filter(dto -> dto.getGroup().equals("connected") // 2.10 正式版
|| dto.getGroup().equals("connected_peers") // 2.11 Beta 1-2
|| dto.getGroup().equals("peers_connected")); // 2.11 Beta 3
}
return stream.map(peer -> new PeerImpl(parseAddress(peer.getIp(), peer.getRemotePort(), peer.getListenPort()),
peer.getIp(),
new String(ByteUtil.hexToByteArray(peer.getPeerId()), StandardCharsets.ISO_8859_1),
peer.getClientType(),
peer.getDlRate(),
peer.getDlSize() != null ? peer.getDlSize() : -1, // 兼容 2.10
peer.getUpRate(),
peer.getUpSize() != null ? peer.getUpSize() : -1, // 兼容 2.10
peer.getPermillage() / 1000.0d, null, Collections.emptyList())
).collect(Collectors.toList());
}
额外的话题:
BitComet 的 WebUI 的列表是不是不支持分页?在 qBittorrent 那里有个问题就是当种子数量过多的时候,因为没有分页,导致种子数量达到一定程度后,过多的 DOM 引发打开 WebUI 时浏览器卡死的问题。BitComet 的 WebUI 刚刚起步,现在改是个不错的时机。
主要还是 WebAPI 的性能问题,能解决掉性能问题,拉不拉平什么的其实都不重要
正如之前我所提出的建议 为外部调用设置专门的接口
其调用方法应 可以对应在winUI的操作
qb的请求方式是个不错的参考
而在鉴权方面 应允许一种较为简单的方法
以方便用户编写简单的脚本
WinUI这个之前有群友建议过我去hook来适配更老,不过这属实超出了我的能力范围。现在有 WebAPI 了绝对是好了很多,但性能问题带来的影响挥之不去。
所以我的疑问大概是明明主线程不繁忙,为什么 http server 的性能会这么糟糕?
以及还有其他朋友反馈 UI 的性能问题。
是不是锁的问题或者跑错线程了?
所以群里很多人问我2.11都出来了,2.10还不发布??
我表示官网正式版发布后才发布呢
如果官网不发2.10就累积到2.11在发,跳过一个版本
问题不是出在并发查询上,是单个查询速度都慢,理想是1-10ms内出结果,这样并发能做到100左右
问题是现在都是几百ms出结果,把这个单次查询慢的问题解决了,并发查询肯定也一起解决了
有关这个问题基本上来说就是dht,比特彗星每隔30分钟主动发dht查询请求不是只发给一个或者极少数人,而是在这个时间同时发给几千上万个DHT节点的所有人,所以有些运营商限制了tcp/udp并发连接数就每30分钟卡一次,之前一直让加个选项控制主动发起的请求数量没加,或者单独限制DHT的udp每秒并发,所以后来发的版本都是默认关闭DHT了,不使用DHT纯靠tracker和pex也效果差不多不受影响,基于tracker服务器提供的响应peer速度更快(实际上导致这个问题的并不是路由器,而是运营商做了限制)
特别照顾黑粉修复打开软件因为DHT产生UDP并发连接数引起断网问题
https://bbs.itzmx.com/thread-100668-1-1.html
配置预设:1.89版本起调整默认设置关闭DHT网络,对DHT有需求请自行在右下角处,点击右键打开(特别照顾黑粉极小部分人群出现打开软件断网问题:下载网盘HTTP文件时候,需要打开比特彗星的DHT网络吗?打开软件后出现断网1分钟禁用功能的解决办法 - 各类教程 - ZMX - IT技术交流论坛 - 无限Perfect,追求梦想 - itzmx.com )
还有极少的概率是TCP的ACK请求,不过目前没听说反馈有运营商限制,如果遇到限制就调整 network.max_connecting_connections
比特彗星的DHT来说,,,更大程度等于服务器超级中心化的超级DHT节点的设计,稳定跑300KB/s的DHT你肯定没见过吧
比特彗星目前的DHT已打开,效果类似这种了,比特彗星客户端自身成为了一个超级DHT节点
router.bittorrent.com、router.utorrent.com、dht.transmissionbt.com、router.silotis.us、dht.libtorrent.org
要做的就是砍请求,主动查询时不要请求节点上的所有人,只取50-100人这样发,和单独限制DHT产生的UDP每秒包,避免产生收到DHT包,和回复对方DHT查询包使用几百KB/s的持续流量,超过dht每秒包限制和queue时,回复包都应该直接drop
是这样,我看了下并发和单请求差不多。不过这是否也意味着 BitComet 的 HTTP Server 只能同时处理 1 个请求(不知道是 HTTPServer 的限制还是有个锁之类的东西)。
正常全功能 HTTP Server 应该是能同时多线程处理多个请求。
只能说 DHT 的实现不规范。Kad 算法应该只需要通知逻辑位置的附近少数几个人就够了。
因为前几天做毕业论文开题,研究过 Kad 算法和相关论文来着……虽然题目最后被毙了x
用 CGNAT 的还是会有限制的。我这边因为还是分配的公网 IPV4 所以并发非常充足。听说内网 IP 的用户并发数很受限。
比较难绷的是 DHT/KAD 当初设计的流量用的应该是很少的。BitComet 的实现指定是有点问题,这个流量跑的可以说是相当多了。
可能本身设计就是作为DHT超级节点来设计的,查阅wiki可以发现比特彗星当年有提供超级节点 router.bitcomet.net
不过现在可以看到这台超级DHT节点服务器已经关闭了
http://wiki.bitcomet.com/making_torrents_with_bitcomet?s[]=dht#bitcomet_multi-server_syntax_specifications
之前一直让做个DHT包控制不知道为什么一直没做,咕咕咕好多个版本到现在了,,,依旧还没有实现上
不过作为服务器确实根本不用考虑这些,因为服务器宽带并不存在并发连接数限制,只有中国大陆一些省份的运营商才搞这种小动作,然后开发者本身也没遇到卡网现象,就咕了吧
一台字幕组BT分流服务器只放500个任务,就可以控制在1000文件内了,一集一个任务,或者一些季度合集
如果需要远程复现的话,我可以发送一下远程的凭据信息。
话说这个 Global Log 应该怎么看?我这里打开 Global Log 没有 WebAPI 的相关日志。
这是内部调试版本才能看到的详细信息,beta版做了删减。我可以单独打个包,带符号文件
如果不方便公开的话,可以邮件到 ghostchu@qq.com
收到了测试版本,并根据指导打开了日志,观察到一些很有趣的事情:
-
日志打印的耗时都非常短,但是我在我的程序这边打印日志发现真实的耗时相当长
-
尽管我的程序向 BitComet 发送了许多的请求,但看起来只有一部分到达了 BitComet 并被处理
-
在我批量启停任务的时候,BitComet 弹出了未响应的窗口,不知道是不是正常现象
更多测试仍在进行
继续测试,我重启程序让程序重新登录 BitComet。
我观察到程序发送登录请求后,BitComet 的 Global Logs 没有任何日志打印。在我等待了约 4-5 秒后,BitComet 一口气处理了三个登录有关的请求(此时程序收到响应并完成了登录过程),然后继续停住一段时间。
停住的时间内,BitComet 似乎对外界的任何 HTTP 请求都不感兴趣。在我这边看起来就是请求超时了。
就像是卡一会儿,然后处理几个请求,然后接着卡住。