分类目录归档:cdn

fredzeng与你一起对cdn,cdn加速,cdn是什么,免费cdn,cdn公司,cdn厂商,cdn技术学习相关知识及探讨!

Wi-Fi现场勘测,分析,故障排查

越 来越多的家庭和企业转向WiFi网络作为其首选的互联网接入的提供方式。无线网络对于终端用户更为便捷,使每个人都能够充分利用其移动设备的优势。无线网络相比传统的有线网络而言,也免除了线接的烦扰和限制。

从管理员的角度来说,WiFi网络虽然有很多的优势,但同时也伴随有一系列必须予以解决的其他挑战。这不仅仅只是为您的所有用户提供充足的连接的问题。您还需要了解您的网络的其他方面,如覆盖区域和信道重叠。

对于我们部分使用家庭WiFi网络的用户而言,我们就是自己的网络管理员。如果您是这样的情况或只是一位具有好奇心的终端用户,您需要了解的您的网络的其中一大特性就是WiFi信号强度。这个值对于您的网络活动效率是一个决定性的因素。让我们深度了解一下WiFi信号以及它们是如何影响您的无线网络使用的。

什么是WiFi信号?

WiFi网络使用无线电波来在不同的设备之间建立通信。这些设备可能包括计算机,移动手机,平板电脑或网络路由器。无线网络路由器是互联网或其他以太网络有线连接和无线连接设备之间的接口。

路由器对从WiFi网络用户那里接收来的无线电信号进行解码并将它们传至互联网。反过来,路由器会将从互联网接收的数据由二进位数据转换成无线电波,传送至使用同一网络的设备。

产生WiFi信号的无线电波使用的2.4 GHz和5 GHz的频带。这些频率要高于电视或手机所使用的频率,相对较低频率能够传递更多的数据。

WiFi信号在传输数据时使用的是802.11网络标准。WiFi网络采用了一系列不同协议的变体。您将会了解到的部分最常见的协议包括2.4GHz频带所使用的802.11n以及5GHz频带主要使用的802.11ac。其他协议您可能还会看到802.11b,它与802.11g是最慢标准。

良好的WiFi信号强度是怎样的?

整个网络覆盖区域内的WiFi信号强度直接影响着用户高效处理各种网络活动的能力。在深入探析怎样的信号强度才适合您进行相应的WiFi网络活动之前,让我们讨论一下 WiFi信号强度是如何测量的

信号强度是以dBm为单位的。它指的是分贝毫瓦,以从0到-100内的负值表示。因此,-40的信号相比-80的信号更强,因为-80距离0更远,因此是一个更小的数字。

dBm是一个对数性的,而不是线性的,这意味着信号强度之间的变化并不是平滑渐进式的。从这个层面来说,3 dBm的不同会使之前的信号强度减半或提升一倍。

能够影响到您的WiFi表现的背景噪音等级也是用dBm表示的。对于噪音等级而言,数值越接近0,就表示噪音等级越高。经测量的-10 dBm的噪音要高于-40 dBm的噪音。

下表揭示了您应当努力实现的最低信号强度,只有达到才能将您的WiFi网络用于各种不同目的。

信号强度限定符适合用途
-30 dBm极好这是可实现的最大信号强度,适用于任何一种使用情景。
-50 dBm极好此极好的信号强度适于各种网络使用情形。
-65 dBm非常好建议为智能手机和平板电脑提供支持。
-67 dBm非常好此信号强度对于网络电话和流媒体视频的使用是足够的。
-70 dBm可接受该等级是确保实现稳定的数据包传输的最低信号强度要求,对于网页冲浪和收发邮件的使用是足够的。
-80 dBm不良实现基本连接,但数据包传输不稳定。
-90 dBm非常差大多都是噪音,抑制大多数功能的实现。
-100 dBm最差全是噪音。

哪些因素会影响到WiFi信号强度?

能够影响到您的网络WiFi信号的有 一系列不同因素。其中部分因素有:

路由器位置

路由器位置的各个不同方面会影响到良好信号的传输表现。这些包括:

  • 路由器的高度 – 您应当将您的路由器尽可能放到高处。将它放在地板或较低的搁板上将影响到其提供强烈信号的能力。

  • 中心位置 – 如果您的路由器放在您的住宅或办公室的中心位置,那么您将获得 最佳WiFi信号覆盖。将路由器放在家里的角落将会导致WiFi信号泄漏并降低您的信号覆盖区域内的信号强度。

  • 来自其他设备的干扰 – 微波炉和无线电话可能使用的是与您的 WiFi路由器相同的频率,能够产生对信号等级造成影响的背景噪音。

  • 墙壁和地板 – 如果在连接设备的位置可以清楚地看到路由器的位置,那么您将会获得最佳WiFi信号。穿越 墙壁和地板进行传输的信号的强度会大打折扣。

保持您的路由器的更新

将您的路由器的设置改成自动固件升级以保持其处于高效运作状态。阶段性地重启您的路由器也是一个比较好的做法,有利于实现良好的信号覆盖。

距离路由器的距离

需要较强信号的设备,如那些用于玩游戏或观看视频的设备,将它们放在靠近路由器的位置可能会获得更好的信号表现。在一些情况下,您可能需要通过使用像路由器这样的附加设备来 扩展您的WiFi信号范围以增强WiFi信号强度。

mysql文本替换

UPDATE w_zshop_goods_sku_images SET path = REPLACE(path, ‘http://qq.com’,’https://qq.com’);
UPDATE w_zshop_commodities SET details = REPLACE(details, ‘http://qq.com’,’https://qq.com’);
UPDATE w_zshop_commodities SET params = REPLACE(params, ‘http://qq.com’,’https://qq.com’);
UPDATE w_users SET profile = REPLACE(profile, ‘http://qq.com’,’https://qq.com’);
UPDATE w_zshop_banners SET pic = REPLACE(pic, ‘http://qq.com’,’https://qq.com’);
UPDATE w_zshop_order_coms SET pic = REPLACE(pic, ‘http://qq.com’,’https://qq.com’);

coturn 添加redis实现对转发流量和转发时长的统计

前言

虽然已经用 coturn 来作为 webrtc 的转发服。 但是我们只做了一个最基本的静态key的加密校验而已。但是对于转发的流量和转发的时长,却没法统计。
但是事实上,对于转发的流量和时长对于我们的业务来说是非常必要的。
刚好 coturn 有提供了一个统计的redis配置,redis-statsdb,这个是就是 turnserver 会将一些统计的数据存到 redis 中。 然后我们去取就行了。
所以要在配置文件里面加上这一个配置:

1
redis-statsdb=”ip=59.57.xx.xx dbname=13 port=6379 connect_timeout=30″

具体文档:

-O, –redis-statsdb Redis status and statistics database connection string, if used (default – empty, no Redis stats DB used). This database keeps allocations status information, and it can be also used for publishing and delivering traffic and allocation event notifications. The connection string has the same parameters as redis-userdb connection string.https://github.com/coturn/coturn/wiki/turnserver
也就是这个参数是用来做状态统计的。 可以用来发布和传递流量, 还有断开和连接的webhook通知。通过这个统计的redis db,我们可以得到这一次转发的开始时间,结束时间,以及转发的流量。
大概的一个截图就是:

1

这边还有更详细的说明: schema.stats.redis
状态的key就是:

1
turn/user/<username>/allocation/<id>/status

举例:

1
turn/realm/pano/user/1531994598:fe909a0a4cde20be0a7bb9fbfdc8d6dc_21_24_18154723/allocation/003000000000002028/status
1

他的值有可能是 new lifetime=… 或者是 refreshed lifetime=…

一个用户名下可能有多个状态。
然后是订阅:

  • 通过订阅: turn/realm/*/user/*/allocation/*/status 这个主题,可以得到一些事件,比如 deleted 事件
  • 通过订阅: turn/realm/*/user/*/allocation/*/traffic 这个主题,可以得到一些信息,比如流量, 当这个配置被删除的时候, 也可以得到通知。

如果是订阅所有的配置,那么就是 turn/realm/*/user/*/allocation/*/total_traffic
因为不能过期,所以redis 的配置文件,要配置这两个:

1
2
timeout 0
tcp-keepalive 60

分析

假设我们已经在使用webrtc的应用上连接上turn server了,并且已经在转发了。那我们就可以看下这个redis跑的统计数据都是什么样的?
接下来先在redis 先sub一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
127.0.0.1:6379[13]> psubscribe turn/realm/*
Reading messages… (press Ctrl-C to quit)
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417691:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003326/status”
4) “new lifetime=600”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417569:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003324/status”
4) “new lifetime=600”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417569:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/003000000000003700/status”
4) “refreshed lifetime=0”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417569:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/003000000000003700/status”
4) “deleted”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417569:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/003000000000003700/total_traffic”
4) “rcvp=0, rcvb=0, sentp=0, sentb=0”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417569:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003324/traffic”
4) “rcvp=1610, rcvb=1607159, sentp=438, sentb=22052”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417569:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003324/traffic”
4) “rcvp=1385, rcvb=1404252, sentp=663, sentb=31187”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417569:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003324/traffic”
4) “rcvp=1407, rcvb=1442093, sentp=641, sentb=30066”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417569:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003324/traffic”
4) “rcvp=1383, rcvb=1408780, sentp=665, sentb=31146”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417691:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003326/status”
4) “refreshed lifetime=0”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417691:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003326/status”
4) “deleted”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417691:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003326/total_traffic”
4) “rcvp=0, rcvb=0, sentp=0, sentb=0”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417569:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003324/status”
4) “refreshed lifetime=0”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417691:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003327/status”
4) “new lifetime=600”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417691:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/003000000000003705/status”
4) “new lifetime=600”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417569:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003324/status”
4) “deleted”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417569:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003324/total_traffic”
4) “rcvp=5785, rcvb=5862284, sentp=2407, sentb=114451”
1

可以看到进行一次连接的话,会分配好几条临时会话。 从下图来看的话,可以看到有 4 条,其实这四条都属于同一个连接。

接下来我们一条一条来分析:

  • 刚开始建立了一条 3326 的临时channel , 生命周期是 600s,也就是 10分钟
  • 然后又建立了一条 3324 的临时channel
  • 接下来的三条分别是,刷新一条 3700 的临时channel ,lifetime 为0,说明是要删除,所以接下来就收到一条 delete 的状态,说明这个临时topic要删除,然后当删除的时候,就会将这一段时间的流量(total_traffic )也传上来。
  • 接下来的4条,全部都是 3324 这一个topic的流量信息。包括收到的字节和发送的字节
  • 接下来的三条是3326,分别是将lifetime 为0,然后delete,最后关于这条临时channel 的流量过来。
  • 接下来的一条是 3324 这一条的lifetime 为 0, 然后是两条新的临时channel 的建立, 然后就是 3324 收到 delete 的状态,和总流量的通知。

总结一下:

1. 一次的webrtc 的turnserver 转发,其实会分配了好几个临时的 channel。

2. 每个 channel 的生命周期和对应的状态

每个 channel 刚开始创建的时候,生命周期只有 600s, 这个可以在 配置文件设置:

1
2
3
4
5
# Uncomment to set the lifetime for the channel.
# Default value is 600 secs (10 minutes).
# This value MUST not be changed for production purposes.
#
#channel-lifetime=600

而且刚开始创建就会有状态通知,内容就是 new lifetime=600
虽然每个channel的生命周期都是 600s, 但是并不意味着,600s 之后,这个channel就会被删除,其实不是的,这个是可以被续的,也就是如果这个 channel 被续了,那么就会有这个状态通知:

1
2
3
4
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532403222:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/004000000000003897/status”
4) “refreshed lifetime=600”

这个说明被续了一个周期了。当然也有不续的,这时候也会有这个状态,不过这时候 lifetime 是 0:

1
2
3
4
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532415366:07a9939e437c9bca97f67b4b74de6a2f_21_24_22819787/allocation/004000000000003905/status”
4) “refreshed lifetime=0”

一旦 lifetime 为0, 就说明这个channel要被删除了。 这时候就会收到 delete 状态:

1
2
3
4
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532415366:07a9939e437c9bca97f67b4b74de6a2f_21_24_22819787/allocation/000000000000001816/status”
4) “deleted”

这时候就说明这条channel已经被删除了。
而且每一个channel 的最长生命周期是可以配置的,默认是 3600s:

1
2
3
4
5
# Uncomment if you want to set the maximum allocation
# time before it has to be refreshed.
# Default is 3600s.
#
#max-allocate-lifetime=3600

所以一个完整的 channel 周期就是 创建-> 续周期(一次以上) -> 删除 (如果续的是 0)
针对这个,我后面试了一下, 在一次长达 一个多小时的webrtc连接, 那个转发流量的channel, 续周期续了7次, 一次 600s, 总的是 7 * 600 = 4200, 比3600 还大了,但是也还没有断开,所以这个也有点奇怪???

3. 流量信息

每一条channel 在生命周期之内,如果有进行流量转发的话,那么就会每隔一段时间就会有 traffic 这个状态过来,注意,如果是 stun 或者 local 这种不走转发的,那么是没有这个事件的:

1
2
3
4
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417569:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003324/traffic”
4) “rcvp=1383, rcvb=1408780, sentp=665, sentb=31146”

而且每次的channel 的生命周期结束之后,也就是 delete 状态,也会收到这一条生命周期的所有的转发流量数据。

1
2
3
4
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532417569:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003324/total_traffic”
4) “rcvp=5785, rcvb=5862284, sentp=2407, sentb=114451”

跟 traffic 不一样, traffic 是真的是转发有流量,才会每隔一段时间抛一次,而 total_traffic 是必会有的,不管是穿透还是转发, 只不过如果是穿透的话,那就是都是 0,比如:

1
2
3
4
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532415366:07a9939e437c9bca97f67b4b74de6a2f_21_24_22819787/allocation/004000000000003905/total_traffic”
4) “rcvp=0, rcvb=0, sentp=0, sentb=0”

每一个 delete 状态,都会跟着一个 total_traffic 事件。 而里面的 这些参数,其实都是 traffic 的所有对应参数的总和。
这四个参数分别是:

1
2
3
4
rcvp: 收到的数据包
rcvb: 收到的字节(byte)
sentp: 发送的数据包
sentb: 发送的字节(byte)

所以我们如果要统计这一次转发的时长的话,那么就要记录这次连接的所有的channel。也就是如果这一次的转发,有5个channel,那么就第一个channel创建的时候,就是开始时间, 当所有的channel 都断开的时候,那么就是结束时间。 一定要所有的channel 都断开,才算转发结束,
而且中间还会有不断的新的channel被创建,这些新的channel也要加入到map里面去。然后每一个channel断开,就从map里面去掉, 一直到最后map为空的话,才算转发结束。算转发的总流量也是一样,每一个channel都会有一段流量。 当所有的channel都断开的时候,加起来就是总的转发流量。

代码实现

刚开始是这样子写的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
package main

import (
“errors”
“fmt”
github.com/garyburd/redigo/redis
“iGong/util/log”
“strconv”
“strings”
“sync”
“time”
)

type OnlineTimeBucket struct {
Data map[string]*OnlineTimeBucketSub
Locker *sync.Mutex
}

func NewOnlineTimeBucket() *OnlineTimeBucket {
return &OnlineTimeBucket{
Data: make(map[string]*OnlineTimeBucketSub),
Locker: &sync.Mutex{},
}
}

type OnlineTimeBucketSub struct {
Timer map[string]*OnlineTime
}

type OnlineTime struct {
Start int64
End int64
Delete bool
TotalTraffIc bool
Rcvp int
Rcvb int
Sentp int
Sentb int
}

var onlineTimeBucket *OnlineTimeBucket
var serverTime = time.Now().Unix()

/*
turn/realm/pano/user/1531882310:7ed1019263ce5e09f3d40a1ca15ae992_21_24_18152992/allocation/000000000000000495/status new lifetime=600
turn/realm/pano/user/1531881513:7ed1019263ce5e09f3d40a1ca15ae992_21_24_18152992/allocation/001000000000000462/status refreshed lifetime=0
turn/realm/pano/user/1531882310:7ed1019263ce5e09f3d40a1ca15ae992_21_24_18152992/allocation/004000000000000899/status deleted
turn/realm/pano/user/1531881513:7ed1019263ce5e09f3d40a1ca15ae992_21_24_18152992/allocation/001000000000000462/total_traffic rcvp=18612, rcvb=894124, sentp=104268, sentb=114206669
turn/realm/pano/user/1531881926:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/004000000000000896/traffic rcvp=1847, rcvb=2052114, sentp=201, sentb=10652
*/

func TurnServerStats() {
conn, err := RedisTurn.GetConn()
sub := redis.PubSubConn{Conn: conn}
if err != nil {
log.Error(err)
}
defer conn.Close()
onlineTimeBucket = NewOnlineTimeBucket()
sub.PSubscribe(“turn/realm/*”)

for {
switch n := sub.Receive().(type) {
//case redis.Message:
// fmt.Printf(“Message: %s %s\n”, n.Channel, n.Data)
case redis.PMessage:
err = forwardStats(n)
if err != nil {
continue
}

case error:
fmt.Printf(“error: %v\n”, n)
return
}
}

}

func forwardStats(data redis.PMessage) (err error) {
fmt.Printf(“PMessage: %s %s %s\n”, data.Pattern, data.Channel, data.Data)
event, deviceId, channel, err := decodeChannel(data.Channel)
if err != nil {
log.Error(err)
return err
}
log.Info(event, deviceId)
switch event {
case “status”:
//统计时长 和在线状态
onlineStatus := decodeDataWithStatus(data.Data)
log.Info(onlineStatus)
addOnlineTime(deviceId, channel, onlineStatus)
case “total_traffic”:
//统计流量 这个事件过来说明转发已经结束 并且只有一个会话是有值的
trafficMap, err := decodeDataWithTraffic(data.Data)
if err != nil {
return err
}
//rcvp 接收到的包数量 rcvb 接收到的流量 sentp 发送的包数量 sentb 发送的包流量
log.Info(trafficMap)
addFlow(deviceId, channel, trafficMap)

}
return

}

func decodeChannel(channel string) (event string, deviceId, channelId string, err error) {
args := strings.Split(channel, “/”)
if len(args) != 8 {
err = errors.New(“channel fail .”)
return
}
event = args[7]
deviceId = strings.Split(args[4], “:”)[1]
channelId = args[6]
return

}

func decodeDataWithStatus(data []byte) (onlineStatus int) {
args := strings.Split(string(data), “=”)
switch args[0] {
//新建
case “new lifetime”:
onlineStatus = 0
//刷新
case “refreshed lifetime”:
onlineStatus = 1
//移除
case “deleted”:
onlineStatus = 2
default:
onlineStatus = 1
}
return
}
func decodeDataWithTraffic(data []byte) (stats map[string]int, err error) {
args := strings.Split(string(data), “,”)
if len(args) != 4 {
err = errors.New(“traffic data fail”)
return
}
stats = make(map[string]int)
for _, v := range args {
statsInfo := strings.Split(v, “=”)
s, _ := strconv.Atoi(statsInfo[1])
stats[strings.TrimLeft(statsInfo[0], ” “)] = s
}
return
}

//记录转发时长
func addOnlineTime(deviceId, channelId string, onlineStatus int) {
if onlineStatus == 1 {
return
}
onlineTimeBucket.Locker.Lock()
timer := time.Now().Unix()
if _, ok := onlineTimeBucket.Data[deviceId]; !ok {
j := new(OnlineTimeBucketSub)
j.Timer = make(map[string]*OnlineTime)
onlineTimeBucket.Data[deviceId] = j
}
switch onlineStatus {
case 0:
log.Info(“new life_time”)
var onlineModel = new(OnlineTime)
onlineModel.Start = timer
onlineTimeBucket.Data[deviceId].Timer[channelId] = onlineModel
case 2:
log.Info(“delete life_time”)
if _, ok := onlineTimeBucket.Data[deviceId].Timer[channelId]; !ok {
var onlineModel = new(OnlineTime)
onlineModel.Start = serverTime
onlineTimeBucket.Data[deviceId].Timer[channelId] = onlineModel
}
onlineTimeBucket.Data[deviceId].Timer[channelId].End = timer
onlineTimeBucket.Data[deviceId].Timer[channelId].Delete = true
}
onlineTimeBucket.Locker.Unlock()

}

//记录转发流量并入库
func addFlow(deviceId, channelId string, trafficMap map[string]int) {
onlineTimeBucket.Locker.Lock()
if _, ok := onlineTimeBucket.Data[deviceId]; !ok {
j := new(OnlineTimeBucketSub)
j.Timer = make(map[string]*OnlineTime)
onlineTimeBucket.Data[deviceId] = j
}

onlineTimeBucket.Data[deviceId].Timer[channelId].Rcvb = trafficMap[“rcvb”]
onlineTimeBucket.Data[deviceId].Timer[channelId].Rcvp = trafficMap[“rcvp”]
onlineTimeBucket.Data[deviceId].Timer[channelId].Sentb = trafficMap[“sentb”]
onlineTimeBucket.Data[deviceId].Timer[channelId].Sentp = trafficMap[“sentp”]
onlineTimeBucket.Data[deviceId].Timer[channelId].TotalTraffIc = true
var isDelete = true
for _, v := range onlineTimeBucket.Data[deviceId].Timer {
if v.Delete == false || v.TotalTraffIc == false {
isDelete = false
}
}

if isDelete {
//计算时间,,流量
var rcvb, rcvp, sentb, sentp int
var end int64
start := time.Now().Unix()
for _, v := range onlineTimeBucket.Data[deviceId].Timer {
rcvb += v.Rcvb
rcvp += v.Rcvp
sentp += v.Sentp
sentb += v.Sentb
if start > v.Start {
start = v.Start
}
if end < v.End {
end = v.End
}
}
accountInfo := strings.Split(deviceId, “_”)
if len(accountInfo) < 4 {
log.Info(“deviceId len fail “, deviceId)
}
total_time := onlineTimeBucket.Data[deviceId].Timer[channelId].End – onlineTimeBucket.Data[deviceId].Timer[channelId].Start
err := InsertTurnServerLogs(accountInfo[3], accountInfo[0], accountInfo[1], accountInfo[2], start, end, total_time, rcvp, rcvb, sentp, sentb)
if err != nil {
log.Error(err)
}
onlineTimeBucket.Data[deviceId].Timer = nil
delete(onlineTimeBucket.Data, deviceId)
}

onlineTimeBucket.Locker.Unlock()
}

按照上面的算法来做的话,当我在用web测试的时候,会出现一个情况:

就是如果 coturn 的连接断开了。但是对于这个username, 他还是会保持一两条临时 channel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532433896:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/000000000000001857/traffic”
4) “rcvp=1466, rcvb=1325047, sentp=582, sentb=29696”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532433896:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003357/status”
4) “refreshed lifetime=0”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532433896:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003357/status”
4) “deleted”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532433896:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003357/total_traffic”
4) “rcvp=0, rcvb=0, sentp=0, sentb=0”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532433896:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/000000000000001857/status”
4) “refreshed lifetime=0”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532433896:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/003000000000003734/status”
4) “new lifetime=600”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532433896:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/001000000000003358/status”
4) “new lifetime=600”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532433896:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/000000000000001857/status”
4) “deleted”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532433896:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/000000000000001857/total_traffic”
4) “rcvp=1466, rcvb=1325047, sentp=582, sentb=29696”
1

明明我连接断开了,但是又重新连接了两条。而且这两条根本不会释放

这个就会导致 isDelete 的条件没法成立,因为总有新的链接没有释放。
而且后面还发现,一次转发,虽然有好几条channel存在,但是真正转发流量的channel只有一条,而且过了一个多小时,还是没有断。所以原则上我们只要去判断这一条channel,就可以知道本次转发的时长和流量了。 其他的channel都不要管。但是如果是stun这种穿透的,因为没有转发流量,所以根本不知道那一条的channel,才是起作用的那一条????

后面发现这种情况其实是一个bug, 之所以浏览器刷新还保持两条turn channel 是因为浏览器在刷新的时候,其实没有明确的给手机端发送断开webrtc的信号。导致手机端其实还不知道webrtc断开了。所以手机端其实是对turnserver连接进行重连了, 这也是为啥会有新的两条channel 的问题。
我试了其他端,比如 ios 端,如果是断开的话,是不会有遗留turnserver 的channel 的,最后全部都会被清掉。因此对于web端,在刷新浏览器,或者是退出页面的时候,都要给手机的发送断开webrtc的信号,并且断开本地的webrtc连接。
所以web端的代码得改下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 关掉 webrtc
stopWebRtcServer: function () {
var self = this;
// 给手机端发送一个webrtc 关闭的指令
self.mqttSocket.pub(
self.subCommonStr + ‘toTarget’,
{
“method”: “webrtc.stop”,
},
{
useAes: true,
}
).done(function (data) {
console.log(“%c accept stop:” + JSON.stringify(data), “color:red”);
});
// 清空状态统计的定时
clearTimeout(self.rtcStateMap.timeId);
// 关闭signal长连接
self.mqttSocket.close();
// 关闭webrtc 连接
self.rtcSocket.close();
},

其中 rtcSocket 的 close 事件为:

1
2
3
4
5
6
7
close: function(){
// 停止 video 传输
var video = this._pc.getRemoteStreams()[0].getVideoTracks()[0];
video.stop();
// 关掉 pc 对象
this._pc.close();
}
1

先停止video传输,再释放掉 pc 对象。这时候本来 webrtc work 的时候,是这样的:

看到的消息就是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532677507:ac5fa606abf5ae9d02bd4206625b4911_21_24_18152992/allocation/001000000000004071/status”
4) “new lifetime=600”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532677507:ac5fa606abf5ae9d02bd4206625b4911_21_24_18152992/allocation/004000000000004390/status”
4) “new lifetime=600”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532677507:ac5fa606abf5ae9d02bd4206625b4911_21_24_18152992/allocation/000000000000002210/status”
4) “new lifetime=600”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532677507:ac5fa606abf5ae9d02bd4206625b4911_21_24_18152992/allocation/004000000000004390/status”
4) “refreshed lifetime=0”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532677507:ac5fa606abf5ae9d02bd4206625b4911_21_24_18152992/allocation/004000000000004390/status”
4) “deleted”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532677507:ac5fa606abf5ae9d02bd4206625b4911_21_24_18152992/allocation/004000000000004390/total_traffic”
4) “rcvp=0, rcvb=0, sentp=0, sentb=0”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532677507:ac5fa606abf5ae9d02bd4206625b4911_21_24_18152992/allocation/001000000000004071/traffic”
4) “rcvp=1546, rcvb=1442311, sentp=502, sentb=24802”
1
1

就是建了3条 channel ,然后删掉一条 390 ,保留两条, 后面分别是 210 和 071

这时候我点击 停止webrtc 按钮,图片传输就会停止了。这时候webrtc 就断开了。

这时候就收到了断开的消息了, 210 和 071 都断开了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532677507:ac5fa606abf5ae9d02bd4206625b4911_21_24_18152992/allocation/000000000000002210/status”
4) “refreshed lifetime=0”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532677507:ac5fa606abf5ae9d02bd4206625b4911_21_24_18152992/allocation/001000000000004071/status”
4) “refreshed lifetime=0”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532677507:ac5fa606abf5ae9d02bd4206625b4911_21_24_18152992/allocation/000000000000002210/status”
4) “deleted”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532677507:ac5fa606abf5ae9d02bd4206625b4911_21_24_18152992/allocation/000000000000002210/total_traffic”
4) “rcvp=0, rcvb=0, sentp=0, sentb=0”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532677507:ac5fa606abf5ae9d02bd4206625b4911_21_24_18152992/allocation/001000000000004071/status”
4) “deleted”
1) “pmessage”
2) “turn/realm/*”
3) “turn/realm/pano/user/1532677507:ac5fa606abf5ae9d02bd4206625b4911_21_24_18152992/allocation/001000000000004071/total_traffic”
4) “rcvp=4595, rcvb=4367095, sentp=1549, sentb=74756”
1

这时候channel 就全部为空了。

所以要这样才可以。 但是问题来了,刚才是我们手动点击 停止 webrtc 按钮的,当然流程是对的。
但是如果是直接刷新浏览器呢,那可是来不及处理的????
事实上也是有这个问题,如果直接刷新浏览器,并且不作处理的时候,就会出现最早之前的那种情况,就是手机端认为还连着,所以 turnserver 又建了两条新的 channel 。
所以我后面加了这个事件 onbeforeunload

1
2
3
4
5
6
// 这时候要设置一个unload事件,不然如果直接浏览器刷新的话,手机端是不知道webrtc不用了,他还会连接 turnserver, 导致turnserver 的session 一直在,后面没法算时间
// 设置unonload, 防止直接刷新浏览器的时候,没有传 webrtc.stop 指令
window.onbeforeunload = function(){
self.stopWebRtcServer();
return true;
};
1

每次用户刷新的时候,这时候就会弹出这个窗口,当用户点击 重新加载的时候, 这时候 stop 操作就已经处理完了。

因此就成功关闭了,缺点就是用户每次刷新都会弹窗,并且要点击重新加载。

所以服务端来说的话,整个连接过程中创建的channel 都要做判断,只有当channel 全部断掉的时候, 才判断这个连接结束,这时候才要算时间。虽然每一次连接都有一条channel 在发送流量。所以如果 traffic 有值的话,那么就是这一条有流量统计。所以如果有收到有流量的 total_traffic 的事件 ,那么应该就是 relay 的连接断开了。这时候就可以计算时长并入库了。
所以修改后的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
package main

import (
“errors”
“fmt”
github.com/garyburd/redigo/redis
“iGong/util/log”
“strconv”
“strings”
“sync”
“time”
)

type OnlineTimeBucket struct {
Data map[string]*OnlineTimeBucketSub
Locker *sync.RWMutex
}

func NewOnlineTimeBucket() *OnlineTimeBucket {
return &OnlineTimeBucket{
Data: make(map[string]*OnlineTimeBucketSub),
Locker: &sync.RWMutex{},
}
}

type OnlineTimeBucketSub struct {
Timer map[string]*OnlineTime
}

//map 存在线时间,结束时间-开始时间,,结束之后再存入表

type OnlineTime struct {
Start int64
RefreshedFlow int64
End int64
Delete bool
TotalTraffIc bool
Rcvp int
Rcvb int
Sentp int
Sentb int
}

var onlineTimeBucket *OnlineTimeBucket
var serverTime = time.Now().Unix()

/*
turn/realm/pano/user/1531882310:7ed1019263ce5e09f3d40a1ca15ae992_21_24_18152992/allocation/000000000000000495/status new lifetime=600
turn/realm/pano/user/1531881513:7ed1019263ce5e09f3d40a1ca15ae992_21_24_18152992/allocation/001000000000000462/status refreshed lifetime=0
turn/realm/pano/user/1531882310:7ed1019263ce5e09f3d40a1ca15ae992_21_24_18152992/allocation/004000000000000899/status deleted
turn/realm/pano/user/1531881513:7ed1019263ce5e09f3d40a1ca15ae992_21_24_18152992/allocation/001000000000000462/total_traffic rcvp=18612, rcvb=894124, sentp=104268, sentb=114206669
turn/realm/pano/user/1531881926:26e4cd38fa6fc39fa8fc40fb25fe558c_21_24_18152649/allocation/004000000000000896/traffic rcvp=1847, rcvb=2052114, sentp=201, sentb=10652
*/

func TurnServerStats() {
conn, err := RedisTurn.GetConn()
sub := redis.PubSubConn{Conn: conn}
if err != nil {
log.Error(err)
}
defer conn.Close()
onlineTimeBucket = NewOnlineTimeBucket()
sub.PSubscribe(“turn/realm/*”)

for {
switch n := sub.Receive().(type) {
//case redis.Message:
// fmt.Printf(“Message: %s %s\n”, n.Channel, n.Data)
case redis.PMessage:
err = forwardStats(n)
if err != nil {
continue
}
case error:
fmt.Printf(“error: %v\n”, n)
return
}
}
}

func forwardStats(data redis.PMessage) (err error) {
fmt.Printf(“PMessage: %s %s %s\n”, data.Pattern, data.Channel, data.Data)
event, deviceId, channel, err := decodeChannel(data.Channel)
if err != nil {
log.Error(err)
return err
}
log.Info(event, deviceId)
switch event {
case “status”:
//统计时长 和在线状态
onlineStatus := decodeDataWithStatus(data.Data)
log.Info(onlineStatus)
addOnlineTime(deviceId, channel, onlineStatus)
case “traffic”, “total_traffic”:
//统计流量 这个事件过来说明转发已经结束 并且只有一个会话是有值的
trafficMap, err := decodeDataWithTraffic(data.Data)
if err != nil {
return err
}
//rcvp 接收到的包数量 rcvb 接收到的流量 sentp 发送的包数量 sentb 发送的包流量
log.Info(trafficMap)
addFlow(deviceId, channel, trafficMap, event)

}
return
}

func decodeChannel(channel string) (event string, deviceId, channelId string, err error) {
args := strings.Split(channel, “/”)
if len(args) != 8 {
err = errors.New(“channel fail .”)
return
}
event = args[7]
deviceId = strings.Split(args[4], “:”)[1]
channelId = args[6]
return
}

func decodeDataWithStatus(data []byte) (onlineStatus int) {
args := strings.Split(string(data), “=”)
switch args[0] {
//新建
case “new lifetime”:
onlineStatus = 0
//刷新
case “refreshed lifetime”:
onlineStatus = 1
//移除
case “deleted”:
onlineStatus = 2
default:
onlineStatus = 1
}
return
}
func decodeDataWithTraffic(data []byte) (stats map[string]int, err error) {
args := strings.Split(string(data), “,”)
if len(args) != 4 {
err = errors.New(“traffic data fail”)
return
}
stats = make(map[string]int)
for _, v := range args {
statsInfo := strings.Split(v, “=”)
s, _ := strconv.Atoi(statsInfo[1])
stats[strings.TrimLeft(statsInfo[0], ” “)] = s
}
return
}

//记录转发时长
func addOnlineTime(deviceId, channelId string, onlineStatus int) {
if onlineStatus == 1 {
return
}
timer := time.Now().Unix()
if _, ok := onlineTimeBucket.Data[deviceId]; !ok {
j := new(OnlineTimeBucketSub)
j.Timer = make(map[string]*OnlineTime)
onlineTimeBucket.Locker.Lock()
onlineTimeBucket.Data[deviceId] = j
onlineTimeBucket.Locker.Unlock()
}
onlineTimeBucket.Locker.RLock()
switch onlineStatus {
case 0:
log.Info(“new life_time”)
var onlineModel = new(OnlineTime)
onlineModel.Start = timer
onlineTimeBucket.Data[deviceId].Timer[channelId] = onlineModel
case 2:
log.Info(“delete life_time”)
if _, ok := onlineTimeBucket.Data[deviceId].Timer[channelId]; !ok {
var onlineModel = new(OnlineTime)
onlineModel.Start = serverTime
onlineTimeBucket.Data[deviceId].Timer[channelId] = onlineModel
}
onlineTimeBucket.Data[deviceId].Timer[channelId].End = timer
onlineTimeBucket.Data[deviceId].Timer[channelId].Delete = true
}
onlineTimeBucket.Locker.RUnlock()

}

//记录转发流量并入库
func addFlow(deviceId, channelId string, trafficMap map[string]int, event string) {
if _, ok := onlineTimeBucket.Data[deviceId]; !ok {
j := new(OnlineTimeBucketSub)
j.Timer = make(map[string]*OnlineTime)
j.Timer[channelId].Start = time.Now().Unix()
onlineTimeBucket.Locker.Lock()
onlineTimeBucket.Data[deviceId] = j
onlineTimeBucket.Locker.Unlock()

} else {

}
onlineTimeBucket.Locker.RLock()
if event == “total_traffic” {
onlineTimeBucket.Data[deviceId].Timer[channelId].Rcvb = trafficMap[“rcvb”]
onlineTimeBucket.Data[deviceId].Timer[channelId].Rcvp = trafficMap[“rcvp”]
onlineTimeBucket.Data[deviceId].Timer[channelId].Sentb = trafficMap[“sentb”]
onlineTimeBucket.Data[deviceId].Timer[channelId].Sentp = trafficMap[“sentp”]
onlineTimeBucket.Data[deviceId].Timer[channelId].TotalTraffIc = true
var isDelete = true
if trafficMap[“rcvb”] == 0 {
//当穿透的时候流量为0,并且不会保存回话,所以需要判断所有会话是否关闭 当转发的时候,流量会大于0 ,但是可能会保留回话,所以转发的时候只需要判断流量过来就可以结束
for _, v := range onlineTimeBucket.Data[deviceId].Timer {
if v.Delete == false || v.TotalTraffIc == false {
isDelete = false
}
}
}
if isDelete {
onlineTimeBucket.Locker.RUnlock()
insertFlowLogs(deviceId)
return
}
} else {
onlineTimeBucket.Data[deviceId].Timer[channelId].RefreshedFlow = time.Now().Unix()
}

onlineTimeBucket.Locker.RUnlock()
}

func insertFlowLogs(deviceId string) {
log.Info(“start insertFlowLogs=>”,deviceId)
var rcvb, rcvp, sentb, sentp int
var end int64
start := time.Now().Unix()
for _, v := range onlineTimeBucket.Data[deviceId].Timer {
rcvb += v.Rcvb
rcvp += v.Rcvp
sentp += v.Sentp
sentb += v.Sentb
if start > v.Start {
start = v.Start
}
if end < v.End {
end = v.End
}
}
accountInfo := strings.Split(deviceId, “_”)
if len(accountInfo) < 4 {
log.Info(“deviceId len fail “, deviceId)
}

err := InsertTurnServerLogs(accountInfo[3], accountInfo[0], accountInfo[1], accountInfo[2], start, end, end-start, rcvp, rcvb, sentp, sentb)
if err != nil {
log.Error(err)
}
onlineTimeBucket.Locker.Lock()
onlineTimeBucket.Data[deviceId].Timer = nil
delete(onlineTimeBucket.Data, deviceId)
onlineTimeBucket.Locker.Unlock()
}

//程序关闭时调用,,记录 使用时长
func forceInsertTurnServerUseLogs() {
onlineTimeBucket.Locker.Lock()
log.Info(“start forceInsertTurnServerUseLogs”)
for k, v := range onlineTimeBucket.Data {
//取其中一个的开始时间就可以
var start = time.Now().Unix()
var end = time.Now().Unix()
var rcvb, rcvp, sentb, sentp int
for _, v := range v.Timer {
rcvb += v.Rcvb
rcvp += v.Rcvp
sentp += v.Sentp
sentb += v.Sentb
if start > v.Start {
start = v.Start
}
}
useTime := end – start
accountInfo := strings.Split(k, “_”)
if len(accountInfo) < 4 {
log.Info(“deviceId len fail “, k)
}
err := InsertTurnServerLogs(accountInfo[3], accountInfo[0], accountInfo[1], accountInfo[2], start, end, useTime, rcvp, rcvb, sentp, sentb)
if err != nil {
log.Error(err)
}
}
onlineTimeBucket.Locker.Unlock()
}

如果是穿透的话,因为没有流量,所以每次收到 total_traffic的时候,都要判断是不是所有的channel 都断开了。如果是的话,那么就是连接断开了。这时候就统计时长并且入统计。

ssh登录很慢解决方法

使用ssh客户端(如:putty)连接Linux服务器,可能会等待10-30秒才有提示输入密码。严重影响工作效率。登录很慢,登录上去后速度正常,这种情况主要有两种可能的原因:

1. DNS反向解析问题

OpenSSH在用户登录的时候会验证IP,它根据用户的IP使用反向DNS找到主机名,再使用DNS找到IP地址,最后匹配一下登录的IP是否合法。如果客户机的IP没有域名,或者DNS服务器很慢或不通,那么登录就会很花时间。

解决办法:在目标服务器上修改sshd服务器端配置,并重启sshd

  1. vi /etc/ssh/sshd_config
  2. UseDNS no

2. 关闭ssh的gssapi认证

用ssh -v user@server 可以看到登录时有如下信息:

  1. debug1: Next authentication method: gssapi-with-mic
  2. debug1: Unspecified GSS failure. Minor code may provide more information

注:ssh -vvv user@server 可以看到更细的debug信息

解决办法:

修改sshd服务器端配置

  1. vi /etc/ssh/ssh_config
  2. GSSAPIAuthentication no

可以使用ssh -o GSSAPIAuthentication=no user@server登录

GSSAPI ( Generic Security Services Application Programming Interface) 是一套类似Kerberos 5的通用网络安全系统接口。该接口是对各种不同的客户端服务器安全机制的封装,以消除安全接口的不同,降低编程难度。但该接口在目标机器无域名解析时会有问题

使用strace查看后发现,ssh在验证完key之后,进行authentication gssapi-with-mic,此时先去连接DNS服务器,在这之后会进行其他操作

OpenSSH_6.6.1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 56: Applying options for *
debug1: Connecting to kr.worthcloud.cn [107.150.126.57] port 36000.
debug1: Connection established.
debug1: identity file /home/fredzeng/.ssh/id_rsa type -1
debug1: identity file /home/fredzeng/.ssh/id_rsa-cert type -1
debug1: identity file /home/fredzeng/.ssh/id_dsa type -1
debug1: identity file /home/fredzeng/.ssh/id_dsa-cert type -1
debug1: identity file /home/fredzeng/.ssh/id_ecdsa type -1
debug1: identity file /home/fredzeng/.ssh/id_ecdsa-cert type -1
debug1: identity file /home/fredzeng/.ssh/id_ed25519 type -1
debug1: identity file /home/fredzeng/.ssh/id_ed25519-cert type -1
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_6.6.1
debug1: Remote protocol version 2.0, remote software version OpenSSH_7.4
debug1: match: OpenSSH_7.4 pat OpenSSH* compat 0x04000000
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-sha1-etm@openssh.com none
debug1: kex: client->server aes128-ctr hmac-sha1-etm@openssh.com none
debug1: kex: curve25519-sha256@libssh.org need=20 dh_need=20
debug1: kex: curve25519-sha256@libssh.org need=20 dh_need=20
debug1: sending SSH2_MSG_KEX_ECDH_INIT
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: ECDSA 66:cc:4d:4a:e0:88:3d:77:5f:a4:fd:5f:ff:05:5c:94
debug1: Host ‘[kr.worthcloud.cn]:36000’ is known and matches the ECDSA host key.
debug1: Found key in /home/fredzeng/.ssh/known_hosts:3
debug1: ssh_ecdsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: Roaming not allowed by server
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: publickey
debug1: Trying private key: /home/fredzeng/.ssh/id_rsa
debug1: Trying private key: /home/fredzeng/.ssh/id_dsa
debug1: Trying private key: /home/fredzeng/.ssh/id_ecdsa
debug1: Trying private key: /home/fredzeng/.ssh/id_ed25519
debug1: Next authentication method: password

不看好5G的14个理由(附精彩辩论)

6月18日,一位网名为“蓝色海岸”的业内人士,先后在c114论坛发文《不懂国内为什么那么看好5G?》,阐述了他不看好5G的8个理由,引发众多移动通信业界人士回帖反驳。6月22日,“蓝色海岸”再发文《不懂国内为什么那么看好5G之二—绝地反击》,阐述了他不看好5G的另外6个理由,再次引发众多移动通信业界人士回帖反驳。

这场辩论很精彩,很多地方都说得有理有据,有些观点/说法也具有一定的思辨性,下文就摘录其中的精彩内容,供大家参考。

网名为“蓝色海岸”的业内人士:

1、5G网速达10G, 不可能,即使能达到,也毫无意义,因为没有需要,现在光宽带的网速,EPON是1000兆,GPON是2500兆,可实际开通的一般是20兆,有很少部分用户开通到了100兆,为什么不开通2500兆,因为没必要,没意义,现在高清视频的带宽一般在2至3兆,就算下载需要更快一点,但也有限,因为人眼和人脑是有带宽的,太高了人的眼睛和大脑接受不了,就没意义了。既然光宽带都不需要那么高的网速,手机会需要吗?手机的屏幕就那么小,4K清晰度有意义吗?超过人眼能够识别的极限,标清和4K不是一样吗?

2、千兆无线路由器早已有之,但是市场反映平淡,很显然,只增加最后一公里的带宽,骨干网带宽不增加,也就没有意义了,这就好比只加宽家门口的马路,不加宽主干街道、国道和省道的公路,速度能提高吗?运营商和设备商就是这样愚弄用户的,说是增加到百兆带宽了,可是实际上只是增加了一点点。

3、服务器和手机的处理能力有限,宽带网一端连接的是服务器,也就是电脑吧,一端连接的是手机,电脑的PCIE总线速度已达6G以上,但是硬盘速度也就几百兆,而且这样一台服务器要连接很多用户,就算把电脑的处理能力全部用于一个用户,极限也就几百兆,而手机的处理能力就更弱了,这时候电脑的处理能力变成瓶颈了,网络两端的速度上不去,只是一味的增加中间部分,会有效果吗?

4、现在5G的宣传都说下载一部高清视频只要几秒云云,实际上只要下载视频的速度大于播放的速度,人就感觉不到网速的快慢,手机是一边放视频,一边下载的,你让手机下载那么快干什么呢?让手机几秒钟下载完,就可以歇着了,你心疼它累吗?

5、九几年的时候,上网很卡,后来带宽增加了,上网不卡了,看视频还是很卡,用的很不爽,运营商就告诉用户,是带宽不足,你要把56K猫换成ADSL,有了ADSL,又说要换光宽带,有了光宽带,又说要换4G,这似乎已经形成习惯和趋势了,实际上,上网和看视频,ADSL足够了。为什么ADSL不行,那是骨干网带宽不足,为什么骨干网带宽不足,是因为运营商之间互掐,以及骨干带宽资费不肯下调。接入网的带宽早已远超需要,GPON,EPON,千兆以太网,千兆无线路由器,10G以太网,这些技术早就成熟了,可是下载高清视频的速度也没有说就几秒啊,5G同样是在接入网段的技术,凭什么这么一个接入网段的技术,就能大幅度的提升网速呢?现在有个口号,叫4G改变生活,5G改变社会,的确,3G的带宽只有2兆多一点,而且是很多人分着用,是少了一点儿,但是4G看来是足够了,在没有Iphone的时候,3G搞了10年也发展不起来,那是因为没有需要,同样的5G想要发展起来,需求在哪里呢?

6、现在有了高清视频,有了1080P,甚至有了4K电视,网络快一点,还是有那么一点点道理,离开了大屏电视,就手机那么一个小小的屏幕,它的显示面积就那么一点点,它要那么大带宽干什么呢?再说了,有多少人在室外一边走路一边抱个手机看电影?恐怕没有吧,一般都是看看微信呀,上个网什么的,就这么点需要,难道上百兆的4G还满足不了?恐怕几兆就足够了吧。

7、我们的网速到底有多快,我可以告诉,平均每个用户就100K多一点,但是这是平均值,实际上由于统计复用的原因,并不是所有人都在不停的占用带宽,而是轮流使用的,所以大家使用的实际带宽还是挺大的,几兆应该是有的,如果用户和服务器同处网络边缘,也就是通过CDN加速,再宽一些也是可以达到的。这就好比马路就那么宽,但并不是所有人都站在马路上一样。你要更宽,那就变成经济问题了, 并不是技术实现的问题,试想如果带宽像空气和阳光一样随处可得,尽管没人离得开空气,可是又有谁能把空气变成钱呢?这种事情运营商会干吗?这就是说有价值并不等于有价格,没有价格也就是没有经济趋动力,没有经济趋动力谁肯干呢?骨干网平均带宽100多K,接入网要上一万兆,这意义又在哪里呢?

8、 这些都撤远了,就说通信行业,九十年代炒的火热的ISDN,那时候互联网还不普及,ISDN可以通两部电话,还可以通可视电话,可是可视电话因为视频压缩算法不过关,带宽低图像质量差,画面小,无法激起消费者的购买欲望,很多公司投入几亿几十亿美金,都丢到水里了。阚凯力阚大炮当时看准了ISDN没有未来,ISDN技术可以在一根电话线上装两部电话,可是他认为只要再接一条电话线就可以办到了,那样显然更便宜,何必为这个要搞一代新技术,更何况有多少家庭会需要两部电话啊?接下来是ATM,ATM把主要吸引点放在视频业务上,结果同样因为视频技术不过关,ATM无用武之地,胎死腹中。

楼主并不是说5G永远没价值,至少是在目前能看得见的未来,价值还体现不出来,这就很危险了,你说现在看不到也想不到的应用,就炒得火热,到处宣传到处试点,搞了几个试点是花了好几亿,这是在糊弄老百姓啊,还是在套取国家资金啊?阚大炮当年认为3G是皇帝的新装,结果3G的投资的确打了水漂,有人辩解说3G积累的技术,在5G时代用得上了,还要领先国际水平,可是阚大炮的眼光是很毒的,被他识破的东西要想翻身如同登天,3G时代积累的那些技术能否用在5G上,看来很大的可能性还得落空。

9、 5G现在的确吹的有点邪乎了,刚开始说要搞1G带宽,后来4G+出来了,能上300多兆,这样看来1G带宽好像也不是什么太有吸引力的概念了,然后就搞出个10G出来,这简直就是放卫星了。固网和光宽带现在实用带宽也就几十兆,现在10G的光宽带也已经实用化了,据说到2019 100G的PON标准也将发布,可是用户实际开通的带宽到底有多少呢?这种脱离实际应用,单纯的技术引导能走得远吗? 论坛里有人说5G是低延迟,这恐怕说的是基站到用户之间100多米的延迟吧,这100多米产生的延迟在整个通信链路中微不足道,基站到城域网,再到骨干网,用的就是光纤了,请问这段延迟是怎么解决的?这早就超过5G技术的范围了。决定延迟的根本原因,还是在于城域网和骨干网,这都不是5G技术能解决的问题了,你说5G能解决,那就明确说明这部分是怎么解决,你不要说那些通信专家肯定考虑到了,他们到底是怎么考虑的?

5G号称低延迟,连郎咸平都出来说话了,说5G的速度快于人的神经的反应速度,在胳膊上扎一针,大脑还没感觉,5G网另一端就已经知道了,这种说法的确够让人震惊,可是光通信的速度早就有这么快了,可就是没人那么说,这不是故弄玄虚糊弄无知群众么?5G厂商够厉害,连著名经济学家都搬出来造势了。5G要想实现低于光宽带的延迟,那得费九牛二虎之力,这一点连任正飞自己都承认还解决不了,可是媒体上都吹的跟真的一样了。

10、5G所使用的频段是毫米波,在这个波段,电波基本是直线传播,绕射和透射能力都很差了,另外5G基站的覆盖范围也很小,可能只有几百米吧,发射功率和带宽呈正相关,带宽加大,发射功率急剧增加,而手机的发射功率是有限的,这就决定了5G基站的覆盖范围很小,大概100多米到几百米的样子吧(网上有文章号称 5G基站能覆盖20公里,到了那个距离,带带还剩多少,还有什么使用价值,有良心的工程师自己知道),这其实比WIFI的覆盖范围也多不了多少了。面积与覆盖半径的平方成正比,这就意味着5G基站的数量和密度可能是4G的5到10倍,这正是设备商努力鼓吹5G的原因了,可是那么密集的基站,手机即使很低的移动速度,也会频繁切换,而切换又会产生很多的延迟和中断,这些问题又怎么解决?这么多的技术缺陷,注定5G如同无线输电一样,描绘的很好,却是个迟早都会破的大泡沫。

11、再说物联网,物联网是5G炒作者最重要的支撑基础,什么万物互联,物物互联。通信说白了,最重要的指标无非就是延迟、带宽和丢包率,这三个指标是基本指标,光通信这三个指标都远优于5G,在这方面有天生的优势,可以说已到了理想化的程度,对5G来说,那是一道永远也不可能突破的墙,现在5G到处宣传,给人感觉好像是什么划时代的技术,可以轻松超越光通信。WIFI加光宽带足以实现物联网的需要,没有WIFI的地方还可以用4G,没有5G物联就实现不了啦,不会吧,不要尽搞些新概念吓唬人好不好。网上有人说5G的频谱利用率有多高,就这一点足以说明5G是个好技术,请问5G提升频谱利用率的最终目的不就是在有限的频谱内提升带宽吗?可是如果连提升带宽都变得没有意义了,那提高频谱利用率的价值何在呢?

12、有人说楼主不懂,服务器和电脑不一样,服务器里面的硬盘早就使用光纤连接了,但是光纤连接的仍然是硬盘啊,硬盘的速度是瓶颈,你用什么连接速度也上不去,这就是木桶理论了。实际上,现在使用的服务器大多仍是PC机,只是PC机集群而已,但也有极少量的小型机,硬盘仍是最主要的存贮介质,你说可以搞个缓存,那样存取速度就会提高,但那毕竟是极少量的,缓存的容量跟硬盘怎么比啊,那是成千上万倍的差距啊,没有大规模推广的技术,证明是没有商业价值的。

13、有人又说到AR,VR,反正这些技术还没走进人们的生活,大家但吹无妨,这两种技术可能需要三十多兆的带宽,4K高清需要16兆带宽,也就是这样了,这也不需要10G带宽啊,有人又说了,基站的带宽是大家共享的,你以为光宽带的带宽就不是共享的吗?这种AR,VR要戴个大眼镜捂住双眼,你不怕在外面走路会撞电线杆吗?这AR,VR恐怕还只能在家里用用吧,在家里用当然是WIFI和光宽带更好了,5G信号要穿透家里的墙,那丢包率和延迟还不得蹭蹭的往上窜啊。回到物联网的问题,物联网所连的物,绝大部分应该还是在室内吧,室内当然是光宽带和WIFI的地盘了,5G信号穿墙到室内,那信号还不知道差到哪里去了?

14、通信行业这些年的走向,让人摸不着头脑了,就说SDH,明明在延迟、带宽、丢包率三个指标上都远优于PTN,也远优于IP网,却被说成是淘汰技术,许多地方拆了SDH上PTN,结果E1线路经常帧失步,你说这不是在开历史的倒车么?这说明一些人的确可以颠倒黑白,指鹿为马啊?我们还要被那些所谓的技术专家糊弄到哪里去?这已经到了对那些技术专家万分警惕的时刻了,弄不好就会被他们带进坑里去了。

网名为“winnyterry”的业内人士:

唉,再见文科生另一神论,其实论调和理据和上一篇一样,只是写得长了一点。回复较为费时。

首先,这篇神论第一段的逻辑就有问题:楼主的逻辑是:任何技术的发展,都必须先有大需求,再去发展技术。否则就是冒天下之大不讳。但我回忆了一下中学小学学过的中国五千年,和世界近两百年的发展。中国和世界都是在矛盾和失败中前行。人类的每一个成功的发明,一开始的需求其实都和移动通信技术很相似,需求不明显,但发明出来后,这个需求就极之可能变种成爆发式的增涨。

其次,楼主纠结国内为什么看好5G,我想说,移动通信技术从电报通信开始,一直到现在的4.5G,就不只是国内的事,而是全世界的事。5G技术也不只是国内在准备,全世界都在准备,看不看好另说。但如果全世界都5G,就中国4G,我就一定不看好了。中国从电报通信到现在,一直在全球通信产业中都处于模仿跟进付专利费的地位,这个局面直到3G开始有了松动,4G开始有点点的话语权,再到5G话语权又会再增加一点。这种进步对于中国通信产业的意义并不是4G有300Mb/s,5G有1Gb/s这么简单的对比可以概括的了。

再次,wifi与5G对比的问题。坦白说,wifi通信和移动数据通信其实分属于两种不同的群组技术,wifi是计算机通信群组技术,5G是传统移动数据通信技术。这两种技术从2G时代起就一直在对抗,希望获得移动通信的话语权。但自己从传统移动通信技术不停的更新迭代,wifi的速率和容量优势早已不复存在。再加上现在全球特别是中国的通信资费以火箭速度下降,wifi注定在未来是小众应用,只剩下企业内网和大型mall用于宣传之用。根本不可能再回复在2G、3G时代的火爆。可以预料,在5G时代,wifi衰落的速度会更快。作为我本人,从2008年起就很少用到wifi了,除非我所在的那个地方完全没有3、4G信号。但这基本上在我全国跑的经历看,这不可能出现。

最后,我实在无法理解楼主说的:“请问5G提升频谱利用率的最终目的不就是在有限的频谱内提升带宽吗?可是如果连提升带宽都变得没有意义了,那提高频谱利用率的价值何在呢?”再次强调,频谱利用率的要考虑是主要是如何在有限的无线频谱下,容纳更多的并发数据。这点比速率的提升更重要。如果GSM一个载扇能容纳200个客户在线,但WCDMA一个载扇能容纳400个客户在线并能保持超过2G的速率,FDD一个载扇能容纳800个客户在线并能保持3G的速率……你还会认为频谱提升没有意义吗?!

网名为“jeffyko”的业内人士:

个人角度,看5G这个问题,如下几点:

(1)相比4G,物理层上没有重大突破,速率的增加无非是通过更高阶mimo更大带宽来实现,

(2)时延上的改进一是架构的优化,二是芯片技术的提高

(3)iot/mtc未来可能会有很大应用价值,毕竟与每个人的生活息息相关

(4)如楼主所述,路铺的宽又如何,应用在哪里?

所以,不要把5g吹的太悬,最终它也要走下神坛。如同volte一样

网名为“winnyterry”的业内人士:

唉,又见文科生神论!通篇的着眼点只有:速度。太片面了。每一代移动通信技术的革新,其它有三点是最重要的,按重要程度排序是:频谱利用率,时延,网速。

频谱资源不论什么时代在移动通信领域都是最为稀缺的,如何在有限不可再生的无线频谱下,容纳更多的并发数据,这是每一代移动通信进步最重要的出发点。特别是物联网时代,万物互联,频谱利用率不提高,一切都是空谈。

其次是时延,现在4g时延基本上能在20毫秒内,对于打游戏,是够了,但如果是VR应用和智能导航呢,又太慢了,测试要在8毫秒内,智能导航才不会错过执行指令的最佳时点。而5g据说时延能控制在5毫秒内。

而网速仅仅是每一代移动通信技术中重要性排在第三位的,可以说只是在提高频谱利用率和降低时延时顺便提高一下而已。对于用户而言,网速的感知最为明显,运营商设备商的宣传着墨于此不难理解,而前面的两点对于用户的感知远远没有第三点的网速明显,但切勿因此就认为移动通信技术就只是网速的提高,这样就大错特错了。

网名为“heipang”的业内人士:

有人说楼主是文科生观点,其实很多通信业内从业多年的人也会有类似观点。说几个自己的想法:

1. 视频是推动宽带发展的需求,但真的作用有限,有些厂商在大肆鼓吹视频和IPTV,其实无非是想多卖设备带宽,体验、运维这些问题在IP网络里没有提供有效的方案解决。

2. 有些需求真的是我们普通上班族体验不到的,每天早出晚归,三四十岁的人了,哪有时间玩游戏,VR/AR这些将来一定对网络的质量要求很高,也许要等到它们渗透到每个生活的角落,你才能感受到。

3. 物联网,个人觉得在部分场景里用处比较大,比如工业、农业、娱乐园区里,家里那点东西真的需要都联网么,有那个精力多陪孩子读点书吧。

4. 法律法规的建设如果不完善,大家怎么放心去联网,家里装个IP摄像头被入侵了咋办,放在云上的视频被流出怎么办:)当然这个担心有点多余,我们的发展模式一直都是野蛮生长再逐步约束。

网名为“risse”的业内人士:

不知道楼主为何这么抵触。带宽大延迟低,不好吗?难道想回到56K的时代?一张图片显示出来都要10来秒!

标清、高清、4K的视频真的是有很大的差别,不要看到现在网站上的在线播放视频,那些都是压缩了的,只是分辨率没有变而已,有机会你下载北京烤鸭完整版的4K视频看看,就知道区别了。

看了你所说的那么多,感觉你就像老一辈的那种没技术的技术而已。

时代的进步,离不开网络的发展,2G的时候你用手机玩游戏?3G的时候你用手机看视频?4G的时候这些都有了吧!5G的时候就不是简简单单的这些应用了。

网名为“jiu_mao”的业内人士:

各位,技术发展和业务的发展是相辅相成的,没有业务强有力的驱动,不会这么快产生一代又一代的通信技术的。5G也是如此,相信现在有很多炒作的概念,但我觉得更主要的动力还是来自于整个社会的进步、人们更高的需求。

楼主,从你鼓吹5G不如wifi加光宽带这一点来看,我觉得你可能是资深的工程师,但绝不会是移动通信相关的工程师!

网名为“frewave”的业内人士:

3GPP定义的5G最大速度是20G,这是指整个基站的速率,分配到个人的没那么多,5G的进步是通过新的技术极大提升频谱效率和基站容量,对于现有的技术,运营商为何不敢像固网那样包月?到了5G极快的的速率,低廉甚至包月的流量,极大的扩展了移动互联网的使用范围(包括万物互联),这些比固网更便利,基础设施上去了,应用才能推广,在2G时代,不可能有微信这类的应用。对于VR、AR这些应用,就像3G时代的智能手机,只有硬件条件到了,才会推广应用。4K的VR只是入门,楼主说的十几兆就够了,这是经过200倍的视频压缩比才能到的,在对延迟不敏感的视频场景问题不大,对直播或游戏就有问题了,这也是为何HTC的VR要有线连接。一两年后8K的VR才是基本配置。

楼主可能只是做固网的,对移动通信的理解还是不深!

网名为“lovebugzhang”的业内人士:

我觉得楼主还是有很多地方没理解上一贴那么多人反驳你的地方,特别是对频谱利用率,还有服务器的传输速度的理解有点问题。5G有很多优势,,低延迟只是其中之一,而且你逻辑并不清晰,低延迟是优势,自动驾驶是应用,不可混为一谈.你不可能因为自动驾驶这个应用距目前太遥远,就认为整个5G是忽悠的.

网名为“winddt”的业内人士:

立场影响观点。

在4G时代,就有wifi+光取代LTE的说法,结果大家都清楚了,各自都发展的很好。这个时代是你可以发展的很好,但你的光芒不是一定要让别人暗淡无光。

5G时代,wifi+光本就已经纳入5G系统的一部分了,这个在去年的IEEE802会议上已经确定了,以前还可以说lte和wifi两者互为补充,5G时代移动宽带和无线宽带深度融合,均成为整个5G系统的的重要组成部分。

网名为“cano”的业内人士:

之前在公众号上看过一篇关于5G的批评文章,有理有据,深以为然。这次本来是抱着寻找同道中人的念头入坑,没想到大失所望。

拜读了LZ第一篇文章之后,我就有了一个猜测,也闻到了一股熟悉的味道。在读了第二篇后,我觉得,我的猜测和那股味道终于被证实了。

楼主应该是搞固网接入和光通信的吧,从这两篇中大谈ISDN、ADSL、EPON、GPON、STN、PTN这些就能看出来。另外,楼主应该是北邮某教授的铁粉吧,第一篇中只是闻到的味道,第二篇中直接就点出了,呵呵。不过自从在某教授狂喷3G的文章中发现一个初中生都不会错的大漏洞后,我和某教授的文章基本就拜拜了。

我觉得LZ对于无线通信的基础知识,对于5G的基本目标和场景都缺乏最基本的认识。

有线通信和无线通信最大的不同在于信道。有线通信可以毫不费力的搞到一组正交信道,无线就要头拱地;有线通信发现一根管子不够了,再加一根就是了,无线还是头拱地……

对于5G的三大场景,或许那些回复也没说清楚,还请LZ自己回去看看。另外,请楼主注意,现在4G的基站也是对用户数和并发业务数有限制的,而且没你想象的那么多。

阿里云, ucloud, 青云 mysql 性能 简单测试

这三家我都有使用

先说 使用感受

  • 青云最专业,后台控制面板也好用。关机只收部分费用也非常适合做测试机器
  • 阿里云没什么要说的,很均衡。不折腾就上阿里云。 就是有几次无故重启不通知
  • ucloud 问题很多,比如 购买的 IP 无法访问 mailgun, 创建主机失败,只能删了重新创建。 网络突然故障, github 无法 clone

这几天有想法 测一下 这三家提供的 mysql 读写性能如何, 于是写了下面的脚本。
先说一下这三家 mysql 的配置:

  • 青云是最低一档的 1 核 2G mysql5.5 , 配置默认
  • ucloud 是最低一档 600M 内存, mysql5.6 标准版,默认配置
  • 阿里云是 第二档 600M 内存, mysql5.5 ,默认配置

所以这是一个不严谨的测试,因为这些机器都是早就买好的。所以无法做到测试环境一模一样。

测试结果:

每家各测试多次,结果比较稳定,就选取其中的一次结果:

青云

INSERT ONE 3.25666999817
INSERT MANY 0.217604875565
QUERY 3.51868581772

ucloud

INSERT ONE 5.17626905441
INSERT MANY 1.33850288391
QUERY 2.40842795372

阿里云

INSERT ONE 5.36786603928
INSERT MANY 0.239859104156
QUERY 5.58612704277

测试脚本:

# -*- coding: utf-8 -*- import os import time import random import base64 import MySQLdb MYSQL_HOST = '127.0.0.1' MYSQL_PORT = 3306 MYSQL_USER = 'root' MYSQL_PASSWORD = 'root' MYSQL_DB = 'bench_test' max_num = 10000 conn = MySQLdb.connect( host=MYSQL_HOST, port=MYSQL_PORT, db=MYSQL_DB, user=MYSQL_USER, passwd=MYSQL_PASSWORD ) # 数据库需要提前建立好,但是表不用 cursor = conn.cursor() sql = """create table if not exists test ( id integer not null primary key, age integer not null, name varchar(255) not null )""" cursor.execute(sql) conn.commit() cursor.close() # 生成测试数据 DATA = [] for i in range(max_num): DATA.append((i+1, i+1, base64.b64encode(os.urandom(64)))) def insert_one_test(): cursor = conn.cursor() cursor.execute("delete from test") start = time.time() for value in DATA: cursor.execute('insert into test (id, age, name) values (%s, %s, %s)', value) conn.commit() cursor.close() print "INSERT ONE", time.time() - start def insert_many_test(): cursor = conn.cursor() cursor.execute("delete from test") start = time.time() start_index = 0 batch_amount = 2000 while start_index < max_num: values = DATA[start_index: start_index+batch_amount] cursor.executemany("insert into test (id, age, name) values (%s, %s, %s)", values) start_index += batch_amount conn.commit() cursor.close() print "INSERT MANY", time.time() - start def query_test(): cursor = conn.cursor() start = time.time() for i in range(10000 * 1): _id = random.randint(1, max_num) cursor.execute("select id, age, name from test where id = %s", (_id,)) result = cursor.fetchone() assert result[1] == _id print "QUERY", time.time() - start if __name__ == '__main__': insert_one_test() insert_many_test() query_test() 

https://cn.v2ex.com/t/233000

共襄盛举,帝联科技成为2017亚太CDN峰会金牌赞助商

机遇与挑战并存。用这句话来形容近两年的CDN行业再合适不过:一方面流量持续爆发,前景看好;另一方面竞争加剧,行业一片红海。这样的行业背景下,即将召开的2017年亚太CDN峰会具有特殊的意义。

“GFIC——2017亚太CDN峰会”由DVBCN&AsiaOTT(众视网)主办,将于2017年4月12日至13日在北京凯宾斯基大酒店(亮马桥50号)2楼举行。帝联科技作为CDN行业的领军企业之一,已经连续第五年深度参与亚太CDN峰会,自首届起从未缺席。

本次峰会,帝联科技将作为金牌赞助商,携重量级产品与技术亮相并发表演讲,与众多行业同仁一起,分享其对于行业发展的见解。



历届亚太CDN峰会全球顶级CDN合作伙伴

作为一家创立12年的老牌网络平台服务商,帝联科技成长、蜕变以及云服务平台形成的内在逻辑,本就代表着CDN行业生态化、精细化和智能化的方向,具有行业指导性意义。

帝联科技依靠分布式数据中心(IDC)起步,积累了广泛的客户群体,为开展CDN业务打下坚实基础。随着行业发展,公司业务重心逐步转向CDN行业。2007年,帝联科技推出7*24全国统一400客户服务热线,CDN平台储备带宽超250G,这也标志着帝联的第一次转型完成,CDN业务占据主导。

随后几年,借着互联网行业流量爆发的热潮,帝联科技资源和技术实力高速提升。截止2016年,公司500+CDN节点遍布全国,海外节点64个,带宽储备超过6.5T,形成了覆盖广、稳定强、价格优的高品质互联网资源,综合实力跃居行业前列。

随着流媒体业务剧增以及行业竞争的日趋激烈,传统CDN服务面临着前所未有的挑战。流量爆发之下,CDN平台构建必须进行升级。帝联科技投入了巨额资金,配置了大量优质设备和带宽资源,聘请了以CTO为首的业内知名技术人才,优化技术团队。

经过一年的努力,帝联科技逐步做到了资源部署精细化和网络链路动态选择智能化。其中,DnDns系统更是较大程度地实现了运维自动化,引领了CDN行业的技术趋势。

据帝联科技CTO洪克柱介绍:DnDns系统由帝联科技投入大量研发资源,完全自主开发而成。DnDns系统基础解系包含UDP/TCP,IPV4/6,泛域名,edns0-client-subnet,高性能Zone文件解析等;智能解析则包含精准动态更新的地址库,高效区域(view)拓扑分级策略,灵活简易的区域配置:个位数的配置文件,DNS切量迅速收敛:IP Ratio等。各项技术指标均处于行业前列。

从央视春晚直播到315晚会,再到近期火热的世界杯预选赛,DnDns系统已经在热点网络视频直播中发挥重要作用,大大的缩短了响应时间,为客户带来更流畅更快捷的服务。

十二年来,一步一个脚印的发展使帝联科技形成了稳固的资源、技术以及人才优势,也积累了超3000 家客户,其中包括腾讯、百度、阿里巴巴、360、京东、搜狐、新浪、网易、央视国际、广电集团、苏宁集团、中国移动、中国安全部门等一系列行业代表企业。并以良好的服务态度与技术升级赢得了客户赞许,在腾讯供应商评分中位居第一。

基础扎实是起飞的前提。帝联云存储、帝联弹性计算平台、帝联监控报警、帝联运营一体化系统等产品和系统方案将会为帝联科技向前发展持续提供动力。未来,帝联科技正在逐步成长为一家集数据存储、分发、计算、安全为一身的云服务平台。

关于2017亚太CDN峰会

“GFIC——2017亚太CDN峰会”由DVBCN&AsiaOTT(众视网)主办,是GFIC系列峰会中,围绕CDN如何为“宽带中国战略”做好基础服务,为电子政务,移动直播,在线视频,虚拟现实,智慧城市,人工智能,互联网金融行业等提供加速传输,云计算,云存储,大数据,安全防护,应用推广,流量变现等专业服务为主题的亚太区最大规模年度盛会。

亚太CDN峰会汇聚了全球多个国家,500多家企业,数千人参与。伴随着互联网高速发展的红利,“亚太CDN峰会”专注于聚焦内容分发领域,邀请来自Akamai、Fastly、Level3、Limelight、Telefonica、Orange、TWC、网宿、蓝汛、帝联、UCloud、云帆加速、阿里云、腾讯云、百度云、乐视、爱奇艺、PPTV聚力、高德地图、京东云、东方明珠、芒果TV、华数传媒等行业内的领袖企业,共同探索下一个互联网时代的内容分发新格局。

直播平台大火,最赚钱却是CDN网宿、帝联、快网、蓝汛、ucloud、腾讯云

   在十年前,视频网站刚刚兴起时,也是这般光景,当时视频网站也有数十家,其中两大巨额的开支,一是带宽支出,二是版权内容的购买成本,这两大成本支出让大多数独立视频网站难以为继,直至消失。最终的结局是优酷、土豆这两家最大的视频网站完成合并,而后又被阿里巴巴全资收购,腾讯视频和爱奇艺风靡,网络视频行业最终成为了互联网巨头们的独角戏。

直播平台步视频网站后尘,钱被传统CDN赚走,最终被巨头收割?

如今,直播平台似乎又要重蹈覆辙。根据IT桔子的数据统计,国内的直播创业平台多达288家,有很多直播平台还融到千万甚至过亿的融资。比如2015年11月,斗鱼TV获腾讯、南山资本、红杉1亿美元B轮融资;B站获超2亿人民币D轮融资;2016年3月易直播获A轮6000万人民币融资等等,而更多的直播创业平台都还在处在A轮。

不过,目前为止,这些直播平台基本上都未盈利,一边需要支付高额的带宽成本,另一边只是高价对明星主播资源的签约争夺,这看起来似乎又是一场类似于网络视频行业的“烧钱大战”,而结局似乎早已写好,在弹药补充足的情况下,有很多直播创业很可能将要倒在黎明之前。尤其是,近一年以来,国内的融资形势不容乐观,这更需要直播创业小心谨慎的“花钱”。

而与直播创业平台们面临的危险境遇形成鲜明对比则是,传统CDN厂商却在这一波直播平台创业浪潮当中,利用自身垄断的带宽资源优势大赚特赚。根据网宿科技助理总裁孙孝思在接受界面新闻记者采访时就表示,目前行业里80%的直播平台是网宿科技的客户。而目前直播创业平台最大的开支来自于带宽成本,在30%到50%之间,这是一家直播创业平台的最大头的运营成本支出,而这些支出基本上都流入了传统CDN厂商手里。

实际上,这些带宽成本的开支完全可以省下来一大半。目前国内能够为直播平台提供CDN服务的并不是仅仅只有传统CDN厂商,此外还有以阿里云、腾讯云为首的云服务厂商,以及以星域CDN为代表的创新型CDN服务商,他们提供的服务成本都要远低于传统CDN厂商。以星域CDN为例,其在今年5月份曾发布专为直播平台提供服务的产品,极速版的价格仅为传统CDN厂商的十分之一,仅为0.5元/Mbps/天;而旗舰版产品的价格更低,仅为0.27元/Mbps/天,只相当于传统CDN厂商的5%。这样的价格可以让直播创业平台的运营成本直线下降,可以使得直播平台逃离开烧钱大战的魔咒,从而能够将钱花在其他增加自身竞争力的用处上。

直播创业平台选择传统CDN,缘于三大行业认知误区

不过,既然创新CDN厂商的产品如此便宜,为何这些直播平台还是愿意选择网宿科技这样的传统CDN厂商呢?这可能是由于直播创业平台对于创新型的CDN服务商的认知误区所造成的,主要有以下三个方面:

第一,直播创业平台对于创新CDN厂商的产品和技术能力没有认识。对于直播平台而言,用户的观看体验至关重要,尤其是需要保证视频的清晰流畅的播放不发生卡顿,因此他们在选择CDN厂商时更倾向于选择传统CDN厂商,认为他们网络节点多,可以最大程度的得到保障。实际上,现在整个CDN行业已经进入到技术革新的阶段,而不再是原来那个粗放发展到时代。很多创新型的CDN厂商通过技术手段突破了原来的行业限制,从而能够以更低的成本提供更好的服务。以星域CDN为例,其首创“无限节点”技术,已经拥有了在全国布建百万量级服务节点的能力,其中包括400余个骨干节点和百万量级末梢节点,并且通过推出智能硬件产品赚钱宝以共享经济的方式首次实现了下沉至家庭内拉取内容数据,从而开辟出了一条总量更庞大、分布更均匀,数据传输距离可近至1km的网络加速通道,此外星域还有其独特的调度技术,以及动态防御和弱网加速技术等,这就意味着,在服务质量方面,创新型CDN厂商丝毫不输传统CDN厂商。

第二,很多直播创业平台对于创新CDN厂商的服务质量没有信心,误认为传统CDN厂商的成立时间更久,技术可能更加成熟。实际上,事实可能恰恰相反,尽管传统CDN厂商运营时间很长,但由于在云服务商和创新型CDN厂商出现之前,面临的竞争压力很小,导致传统CDN厂商在产品方面缺乏更多的创新,更多的是通过在全国各地架设节点来提高加大自己的带宽,而在具体的产品服务方面,尤其是针对不同的垂直行业方面,并不会及时的推出专业化的解决方案。相较而言,新兴的CDN服务商以产品创新立足,创新的意愿更为强烈,以星域CDN为例,其在今年5月推出了针对直播行业的新产品,而且还具体到了泛娱乐直播、教育直播、事件直播、移动户外直播、/全景直播等几个方面,这使得不同的直播创业平台可以选择更加专业化的服务。显然,在成本更低的情况下,创新CDN厂商对于直播创业平台的服务可能更加到位。

第三,很多直播创业平台选择传统CDN厂商主要看重其行业知名度,迷信其之前服务过的知名企业案例,而不是选择能够与其共进退的合作伙伴。实际上,在服务的主动性方面,创新CDN厂商可能更好,而传统CDN厂商由于长期以来占据着资源的垄断优势,普遍缺乏服务意识,更多的将直播平台看作是客户关系,而并不是合作伙伴,这就意味着并不会真正从合作伙伴的角度去着手解决问题,而更多的看重其营业收入,因此在这些年以来,带宽价格从来没有主动降价过,直到像星域这样的创新CDN厂商出现之后,带宽价格才有了小幅降低,但是仍然比云服务商和创新CDN厂商的价格高出许多。而早在2015年6月,网心科技CEO陈磊在接受媒体采访时就指出,传统CDN厂商的服务心态有问题。相较而言,创新CDN厂商更愿意与直播创业平台一起发展,也因如此,在星域CDN直播产品的发布会上,获得了包括小米直播、大鹏VR、触手TV等多家直播创业平台的力挺。

总体而言,在直播创业大火的当下,创业公司随时面临倒闭危险,而传统CDN厂商却赚的盆满钵满,这是非常不合理的现象。如此下去,独立的直播创业平台可能最终也只能是投入到巨头的门下,而如果想要改变这种不利的局面,第一步或许可以从降低带宽成本开始,而创新的CDN服务商无疑是一个不错的选择。

可以节约CDN带宽流量的流媒体P2P(Flash/Android/IOS)

很多朋友关心SRS是否有计划支持RTMFP,是否计划支持P2P,这篇文章详细介绍了SRS和P2P的关系。

Summary

我们所指的P2P,并非传统客户端P2P的方式,譬如ed2k那种协议。我们特指三种P2P:

  1. FlashP2P:Adobe开发的P2P,Flash播放器之间可以互相P2P,分享视频。

  2. AndroidP2P:特指Android的App的P2P方式,Android上HTML5不可能做P2P。

  3. IOSP2P:特指IOS的App的P2P方式,IOS上HTML5不可能做P2P。

这三种P2P都有几个共同点:

  1. 只讨论流媒体范畴的P2P,普通文件和数据的P2P不考虑。

  2. 流媒体传输使用通用协议,譬如flv、mp4或hls,配合CDN完成P2P原始资源的传输,而并非所有的数据都是P2P网络用私有协议传输。

  3. 尽量避免安装额外插件。譬如FlashP2P就在flash播放器上跑(别纠结flash本身就是个插件),只需要集成AS的SDK,不需要额外安装ActiveX浏览器插件。而Android和IOS的P2P,需要集成P2P系统的SDK,只需要安装商家的App,而不需要再安装专门用来做P2P的App。

综上所述,我们可以将Flash/Android/IOS
P2P,简称为P2P。下面讲P2P一种可能的结构,以及SRS和P2P的关系。

Structure

一个P2P系统,可以包含下面几个结构:

  1. 客户端SDK:P2P系统必须提供客户端SDK,集成在播放器或者App中。譬如FlashP2P提供的是AS的库,Android提供的是java的库,IOS提供oc的库。

  2. API调度集群:P2P系统必须支持API调度,弥补DNS的不足,以及提供P2P系统需要的额外数据。API调度就是SDK交互的第一个后端,完成认证、其他服务器资源的分配、流信息、实时调度。

  3. RTMFP集群:或者称为基础协议集群,由API调度返回给SDK可用的服务器,客户端使用RTMFP服务器完成NAT打洞,以及必要的数据传输。

  4. Tracker集群:或者称为伙伴发现协议集群,由API调度返回给SDK可用的服务器,客户端向Tracker请求可用的伙伴节点。

  5. Pingback集群:或者称为实时数据集群,由API调度返回给SDK可用的服务器,并提供给API调度集群调度的实时数据依据,SDK向Pingback集群汇报实时数据。

  6. 流媒体源站集群:或者称为流媒体源,主要负责流媒体数据的生成,和CDN对接,由API调度返回给SDK可用的CDN边缘地址。

可以在SRS基础上完成的结构是:流媒体源站集群、RTMFP集群。其他大多是HTTP协议,主要是P2P系统内部的算法和逻辑处理,适合使用Python或者GO实现。

另外,Pingback集群需要提供10秒级别的系统数据,使用GO或者Spark都可以,数据量小时用GO实现也可以,数据量很大时可以用Spark。

下面详细分析SRS在WebP2P中的位置和状态。

SRS for P2P

回过头来说,SRS现在已经支持P2P中的流媒体源站集群和RTMFP集群了吗?SRS支持了流媒体源站集群,但是RTMFP集群不支持。

所谓SRS支持了流媒体源站集群,指的是SRS能输出一种HLS,能符合一种P2P系统的要求。这种P2P系统就是观止创想的P2P系统,具体参考BravoP2P。也就是说,若使用SRS作为您的流媒体服务器,是可以直接对接到观止的P2P系统的,可以给现有的HLS流加上P2P功能。

SRS为何不支持RTMFP集群呢,有几个原因:

  1. RTMFP目前不开源。

  2. RTMFP和SRS的差异太大,就算支持了RTMFP集群,还只是P2P系统的六分之一,没法用起来。

  3. SRS的目标是提供通用方案,SRS3的Dragon技术,SRS4对接Spark,目前还没有支持P2P系统的计划,P2P系统里面很多是私有方案。

因此,在现在的路线图,例如SRS3(预计2016年发布)和SRS4(预计2017年发布)的路线图中,都没有RTMFP的影子。

也就是说,在P2P系统中,SRS只计划支持流媒体源站功能。下面分开看看各种P2P系统。

FlashP2P

FlashP2P是由Adobe研发的P2P协议,包括握手、NAT打洞、数据传输,Adobe收购了一家做P2P的公司,将这个RTMFP协议集成到了Flash中。

FlashP2P在PC上的很成熟了,稳定性也可以达到商用的要求。从2013年开始,支持FlashP2P的公司也开始粗现,现在除了我们观止创想,还有云某动、快播解散后的一个团队等等。

AndroidP2P

Android手机、盒子和Pad上面支持P2P,这个目前还在发展中。

IOSP2P

IOS手机和Pad上面支持P2P,这个难度比AndroidP2P还大,目前没有消息。

Challenge

上面讲了各种P2P的情况,P2P的挑战有以下几点:

  1. 转换思维对接CDN:CDN最惧怕的就是P2P公司,不是要分他流量那么简单,而是对接起来灰常痛苦。据说有的FlashP2P系统,得在CDN每个边缘节点部署服务器,因为流媒体切片不通用,这不是要CDN的命么?因此首先最大的挑战就是转换为互联网思维,尽量使用通用方案,让CDN爽了P2P系统才能爽。

  2. 保证流畅度:传统P2P可以暂停缓冲个几个小时,而WebP2P直播正在进行时,缓冲个几次用户就刷新页面,这个P2P节点就相当于牺牲了。因此保证流畅度才能保证分享率,如何保证流畅度呢,这个就各显神通了。

  3. 实时调度:P2P的变化非常快,有的用户刷新页面啦,有的系统拖动啦,有的还暂停,有的就喜欢乱点。因此整个P2P的节点信息都是变化很快的,这对实时分析系统有非常大的挑战。

  4. 负载均衡和热备:P2P的集群也需要负载均衡,譬如RTMFP协议就支持Redirect方式,可以实现负载均衡和热备。传统P2P系统挂掉后节点就没法看视频,而一个P2P系统挂掉后依然能看,因为有CDN在那里呢,但是带宽就开始飙升了。而P2P系统的恢复需要较长时间,因此必须使用热备,在出现问题时切换到正常的系统。

这些挑战都是我们曾经遇到的,还包括没有遇到的。

CDN已成云商必争之地 看CDN年整体收入增速800%的阿里云如何放大招?

近日,阿里云PR一改往日规模会议的模式,落脚创业大街,在3W咖啡办起了CDN专项技术媒体分享会。据笔者观察,这是阿里云2016年PR思路的一大改观,与同为BAT级的腾讯云一同走起了小清新路线。从邀请函中明显看出,本场媒体沙龙的主题剑指传统CDN,“传统CDN会更好?”的疑问在本次技术分享中被揭晓。

传统CDN闷声挣大钱的时代已去

随着用户应用需求类型的改变,CDN作为网络的一部分,已经成为企业级市场追捧的焦点之一。因为通过CDN可以更多的把计算和存储推向边缘,实实在在的让用户感受到最真实的体验。所以,当云计算大规模落地,云化CDN越来越受到用户的青睐。

我们知道,传统CDN一直以来,盘踞在产业链条的一端,悄默声的挣去高额利润。但在阿里云首席科学家章文嵩的眼里,这种传统CDN闷声发大财的局面,很快或者已经被打破。“云化CDN会完全重新将CDN定义。”因为随着创新技术的发展,用户应用习惯的更改。更多的应用场景会更多的被推到边缘节点上,不光是云上的计算,也可能变成边缘计算。“CDN可以说是云的入口,对于任何的云厂商来说CDN都很重要,而且CDN一定是云计算厂商的必争之地。” 章文嵩表示。

为什么肯定?原因很简单,可以被主要归纳为两点。第一,云时代里,企业级需求在改变。用户不在单一将CDN当做一个固定资源来所取,而是在其中加入更多计算、存储、网络、安全等多方面需求,而传统CDN厂商并不具备这样的综合技术实力,所以云服务商就有了更大的机会;第二,池化资源是云计算的本质属性,CDN一旦池化,将会带来更多的规模与价格优势,而这也是传统CDN能力达不到的。据介绍,像云厂商或者国内的BAT级别的互联网公司,他们在基础设施规模的建设上都比传统的CDN厂商大得多。整体的规模效应会带来成本下降,从而会带来更低的价格。

CDN的C从内容(Content)到云(Cloud)的改变

“未来三五年,随着云厂商的进入,整个CDN产业的格局将会发生翻天覆地的变化。” 章文嵩预测。

CDN原来的单词是Content Delivery Network,侧重整体应用的内容分发。而随着云厂商在产业内的介入,大部分企业用户的应用构建、传输都将在云上进行,所以CDN的内涵也将逐步转变为Cloud Delivery Network,云上网络分发的印记将更加深入。

“随着用户需求的适时而变,CDN技术的发展将会融合更多的创新思维和前瞻性的理念进去,云厂商凭借自身的综合实力优势,发展会越来越快。未来两到三年,传统CDN服务商光环不在,有可能整个CDN的行业江湖就会易主。” 章文嵩表示。

对此,阿里云CDN事业部总监朱照远用实际案例带来例证。分享当天,他举了阿里云与芒果TV合作打造风靡全球“超级女声”APP的例子。芒果TV对阿里云提出了苛刻的CDN需求:两周打造一个原型出来!其中APP要实现包括视频的海选、直播与终极PK的功能,其中技术实现要能提供视频的转码、网络专用通道、数据库、消息中间件等等十几种的能力。“这对传统CDN是不可能做到的,因为他们解决不了用户的所有痛点,或需求的功能点。传统的CDN只能提供单一的CDN组件,但是客户需要的却是计算、存储、分发、大数据、安全等等系列解决方案。”

所以,传统CDN在面临复杂的业务场景以及复杂的客户需求时,会表现出能力不足,束手无策。在云时代里,单一的内容分发,已经不能满足用户的多样化需求,云化CDN将给用户带来全新选择。

CDN6.0版本有哪些绝杀技?

阿里云CDN发源于淘宝自有CDN,并于2014年3月开始正式对外为提供服务。在商业化服务2周年之际,阿里云发布了经过10年淘宝历练,5次更新迭代的CDN6.0版本。

据介绍,此次发布的极速CDN 6.0版本,除了首次在业界提出Cloud Delivery Network(云分发网络)理念外。还融合了云计算、大数据技术,涵盖视频和移动两个解决方案以及大数据分析、HTTPS加速等新功能,可以为客户提供一站式的云CDN解决方案。

具体说来,6.0版本针对视频类应用推出视频云解决方案,提供一站式视频点播、直播服务,集内容采集、上传加速、存储、码转/截图、鉴黄服务、CDN分发及播放器等功能于一体,极大地优化了客户体验。据测算,视频云端到端时延仅2秒,流畅度95%,在同等清晰度下,码率低30%,这意味着客户可以节省30%的成本。

另外,新版CDN还提供了HTTPS加密功能,可以让客户内容防劫持、防篡改、防窃密,保证通信的安全。

大数据工具也是6.0版本的重要特色。阿里云将打通CDN和“数加”平台的大数据计算产品MaxCompute,客户如果需要,可以一键上传自己的日志数据,使用强大的MaxCompute进行精细化分析数据,让数据产生商业价值。



▲阿里云CDN用户展示

据透漏,移动端的CDN整体解决方案也即将上线,移动加速可提升40%性能,并具备HTTPDNS功能,具有防域名劫持、调度精确、稳定可靠等特点。

2015年阿里云CDN客户数已突破10万,客户规模是传统CDN厂商客户之和的20倍,在整个CDN市场稳居行业第一。业务营收同比增长800%,增长率也比传统CDN厂商的增速快了约20倍。“这一年越来越多的大中型企业级CDN客户采用CDN和云计算证明了我们对于行业前景的判断。企业在使用公共云架构的同时选择了云CDN,其综合竞争优势显著,这与传统IT架构向云计算转变的历史趋势一致。” 朱照远表示。

▲国内500+节点,超过10T带宽,单节点40-300G,海外覆盖6大洲(图示是阿里云CDN有部署节点的国家或地区)