目前已做出软件,但是速度不够,希望大佬们能提供些意见,我自己还是想独立完成的,顺便学习,所以不太想外包,也就不存在骗源码的情况,如果有可以明显提升效率的建议就会按程度给报酬,多人就均分,相同建议只给第一个人,当然实在想接外包的也不是不可以,但是金额范围不变,也是有效果才会给报酬。
整个抢单流程是:刷新单子信息是否出单→开始抢单。
在刷新单子信息时,我现在是用百个 goroutine 循坏执行“ HTTP 请求+读 body+解析 body ”,我觉得“解析 body ”的部分是肯定可以提升效率的,但是“ HTTP 请求”或“读 body ”会不会互斥更高效?
就我自己搭的小服务器来说,是所有操作都并发能更快的得到网站的更改,但这适不适用于大型服务器呢?原谅我不能直接在发单的服务器上做实验。
如果有比较快的 Go 的 HTTP 包或是 JSON 包也可以推荐一下,fasthttp 我试了好像对客户端的提升并不明显,而第三方的 JSON 包使用风格都各不相同,就没有尝试了。
而上面“读 body+解析 body ”是我现在的方案,整个 body 的数据是 JSON 的,但读取前 10 个字符就已经能知道是否出单,所以知道出单后我会用一个 buffer 缓存 body 的数据,通过自己读 {} 是否闭合来知道是否读完,而不是直接读到 EOF,我观测到读 EOF 可能会有延迟,在 Go 的实现里是否只有服务器主动断开时才会得到 EOF ?
然后直接 json.Unmarshal(buf.Bytes()),我是觉得先 I/O 再解析完整的内存数据比较好,但因为我已经有一个检查 {} 的操作了,这里如果把开头的 10 字节和 body 封装成 io.Reader 接口,丢给 json.Decoder 边读边解析会不会更好呢?但 json.Decoder 是解析到 {} 闭合为止,还是要读到 EOF ?
接着是抢单,抢单的请求也需要并发执行吗?我是觉得第一个连接丢包的话可能没有其他并发的请求快。
而抢单请求时,之前未被关闭的刷新信息的请求会阻塞抢单请求吗?如果会,那么有没有好的 HTTP 请求池方案,能够达到关闭之前请求的时间比被阻塞的时间更少?
其他,代理 IP 对抢单有提升吗,是用“本机带宽 /单 IP 最大不被封带宽”数量的代理好,还是用尽可能多的代理占“本机带宽 /代理数量”的带宽好呢?
就先说到这里吧,其他的想到再补充,其实我更想知道有没有被我忽视的地方,多线程数据同步的话,除了最后的结果我是用 channel 发送到主线程,在并发任务里我都是通过 atomic 变量判断有没有完成该任务,应该不存在阻塞,问题就是上面说的过时的请求要不要主动关闭😂
1
wenbinwu 2018-07-18 20:56:18 +08:00
最多才 800,还可能跟别人平分?
|
2
torbrowserbridge 2018-07-18 20:58:48 +08:00 via Android 3
看完你这段描述浪费的时间都不止 800 了
|
4
gam2046 2018-07-18 21:04:41 +08:00 2
@torbrowserbridge 老哥收入有点厉害的。算看的慢一点,30 分钟看完,值 800。一天 8 小时工作,12800 元了。一个月 21.75 个工作日,税前月薪 27.84 万。
对于楼主的情况,是否能够先解构一下各个部分的大致耗时占比?先看一下目前的情况,主要时间消耗在哪里。是网络请求,解析内容,还是其他方面慢了,再做针对性的操作。 |
5
aru 2018-07-18 21:04:44 +08:00 1
1. 正常情况下,解析 json 要比 http 请求快很多倍,你可以通过多次循环并打印日志来验证这点
2. 并发抢单服务器端可以做了限制 3. 代理一般都挺慢的,不可靠。如果会达到限制,那就用多代理吧,最后下单最好直接本机下 |
6
torbrowserbridge 2018-07-18 21:10:20 +08:00 via Android
@gam2046 夸张的手法😄
|
7
angryRabbit 2018-07-18 21:20:55 +08:00
没看完,太长了
|
8
gamexg 2018-07-18 22:09:07 +08:00 2
不知道你抢的什么网站的单,但是数百个并发请求不怕被封?
>在 Go 的实现里是否只有服务器主动断开时才会得到 EOF ? Body.Read ? http 协议有 3 种表示 body 结束的方式,其中两种不依靠 tcp 连接关闭,go 能够正确识别,另一种依赖 tcp 连接关闭,不过 http 服务器发送完内容会立刻关闭,不会影响速度。 json 流式解析不需要解析到 EOF,到 } 就结束,你可以试下,连续多个 {} 可以解析多次。 go http 内部有个 tcp 连接池,池空了会立刻创建新连接,但是不确定是否有连接数限制,应该没有。 一般 http 池不会出问题,极端情况基本见不到不需要考虑。 实际觉得不需要在意本地 json 解析等的速度,这个相对于网络耗时应该可以忽略不计。 真想提高速度,先确定对方服务器位置,直接租同一机房的。 |
9
pathbox 2018-07-18 22:14:02 +08:00 via iPhone
耗时在网络上,办个网速贼好的服务器,离抢单服务越近越好,速度可能可以翻翻
|
10
zhs227 2018-07-18 22:32:28 +08:00
一般耗时都在网络上,解析库上来说不是最关键的。如果想优化解析这部分的逻辑的话,直接把 rsp.Body[:10]出来,用 string match 一下,不需要做 unmarshal。觉得有必要再 unmarshal,这样可以做到 zero copy。
|
11
yulon OP @gamexg 某国企网站,只是流量大的时候会封 IP 几分钟,外包的网站估计员工也不怎么会用,流量大的几天都是强制人员驻点抢单,已经拉了条本地企业宽带专供一台主机😂
|
12
yulon OP @zhs227 恩,所以我说了知道出单才会继续读,因为信息数据有点多,原来全部读完再解析都要比别的公司慢一秒,现在是同一秒了,但还是差那么几百毫秒。。。
|
13
RangerWolf 2018-07-18 22:42:45 +08:00
不知道目前你说的不够, 是个什么程度。 什么程度才够?
另外真的很好奇贵司的业务。。。 强制抢单? |
14
realpg 2018-07-18 22:50:08 +08:00
上海拍车牌?
|
15
LucasLee92 2018-07-18 22:54:14 +08:00
拍车牌,抢火车票之类的业务
|
16
yulon OP @RangerWolf 某物流公司,网站是抢货单的,而且还和网站有点 PY 交易,但是某段时间开始所有物流公司都开始用工具,我们老板有很多别司没有的权限,但在工具面前毫无优势,其实现在已经优化到所有公司平均水平了,就是想争第一吧🤣
|
17
xiangyuecn 2018-07-18 23:02:23 +08:00
时间(单位毫秒) | 事件
00.000 | 发起请求 05.000 | 远程服务器接收请求并处理 25.000 | 远程服务器处理完毕,开始回传数据 35.000 | 数据接收完毕,开始解析 35.001 | 数据解析完毕,拿到了 json 对象 来试试负优化: 1、网速有点影响,提高点网速,在他们家同一机房开个服务器吧,速度妥妥的 2、网速有点影响,按你的思路,流式读取数据,接收前几个字节能判断出结果就直接关闭连接返回,省一点点时间 3、重量级的还是人家的服务器处理速度,卡个 10-20ms 才开始返回第一个字节数据很正常,基本上没法优化 4、json 解析不耗时间,优化了也没叼用 实际情况是一个完整请求至少耗时 100-300 毫秒(滑稽 |
18
Lax 2018-07-18 23:13:02 +08:00
网络请求时间,一般远远大于在本地 cpu 中计算的时间消耗,看看服务器之间的网络延时,尽量优化一下 /换个机房。
只读前几个字节可能会少占用几个计算周期。不过网络传输数据包的长度相对固定( MTU ),不会因为少读后面的字节而减少传输时间。可以让程序在 TCP 层面进行处理,减少 HTTP 的额外等待。 并行太多,调度开销就大,有条件可以试试减少并行任务数。 |
19
IvanLi127 2018-07-19 01:51:48 +08:00 via Android
基本上是网络问题,你在他服务器同机房里租个机子吧
|
20
fiht 2018-07-19 08:03:11 +08:00
发个 HTTP 包带上 etag 信息试试?
或者自己构造一个 HTTP 报文用 socket 发过去只取前 2048 个字节? |
21
reus 2018-07-19 09:07:00 +08:00
想独占蛋糕,就不怕同行把桌子掀了?
|
22
soulmine 2018-07-19 10:05:22 +08:00
你这都快是高频交易了吧 这么在意延迟 为什么不用 C++写
|
23
lihongjie0209 2018-07-19 10:22:28 +08:00
@soulmine #22 高 io 操作用 c++能上天?
|
24
yulon OP |
25
hoosin 2018-07-19 11:09:13 +08:00
我觉得看完这个需求,就值 800 了
|
26
luw2007 2018-07-19 11:35:08 +08:00
以前用 go 做过 p2p 金融抢单,大致说一下软件思路。
调度进程,业务进程分离。采用 tcp 协议,内网部署。 调度进程负责管理资源(帐号,对方服务器的外网地址列表,代理列表,业务进程 ...) 业务进程只管获取资源和请求和解析并回传。 最终干赢其他对手,甚至于把金融网站打崩(调度里面的动态计算任务间隔,配置成 0 了)。 起到最大作用的原因并非代码层面。 ==>价值 800 元的经验在这里<== 而是找到对方服务器所在机房,并且拿到了源服务器。请求相应时间从 200ms 下降到 40ms。 |
27
pxlxh 2018-07-19 12:10:19 +08:00
看完楼上的感觉楼主是来羞辱知乎 er 的。
|
28
2379920898 2018-07-19 12:27:27 +08:00
给 1 万都不干, 免费送你 黄马褂 手套
|
29
yulon OP @2379920898 你这种水平要能干成我给你 5 万,要走开源众包还是码市?
|
30
yjd 2018-07-19 13:15:20 +08:00
你们考虑过那个网站服务器,带宽的感受吗。被你们这么多家抢单再分摊下,还怎么快。23333
|
31
woscaizi 2018-07-19 13:24:42 +08:00 via iPhone
搞过类似的,是一个虚拟货币网站抢交易单子。
开始我能把网站所有单子抢了。 50 个线程,每个线程间隔 10ms,单台电脑,带宽 100M。 后来网站做了限制,单账号对单子列表的刷新限制到 1 分钟 1 次。 然后我就放弃了。 针对你的情况。 我想网络层不是问题,增加账号做新订单的刷新检测,检测到后发给想下单的账号做下单操作。试想下,如果你 1000 个账号做刷新,每个账号每次检测间隔 30 秒,一秒钟起码你可以有 30 个账号做检测,相当于 30ms 刷一次。 |