事件加工处理平台的必要性,事件管理平台介绍
804
2022-10-20
本文目录一览:
缓存好处:高性能 + 高并发
数据库查询耗费了800ms,其他用户对同一个数据再次查询 ,假设该数据在10分钟以内没有变化过,并且 10 分钟之内有 1000 个用户 都查询了同一数据,10 分钟之内,那 1000 每个用户,每个人查询这个数据都感觉很慢 800ms
比如 :某个商品信息,在 一天之内都不会改变,但是这个商品每次查询一次都要耗费2s,一天之内被浏览 100W次
mysql 单机也就 2000qps,缓存单机轻松几万几十万qps,单机 承载并发量是 mysql 单机的几十倍。
在中午高峰期,有 100W 个用户访问系统 A,每秒有 4000 个请求去查询数据库,数据库承载每秒 4000 个请求会宕机,加上缓存后,可以 3000 个请求走缓存 ,1000 个请求走数据库。
缓存是走内存的,内存天然可以支撑4w/s的请求,数据库(基于磁盘)一般建议并发请求不要超过 2000/s
redis 单线程 ,memcached 多线程
redis 是单线程 nio 异步线程模型
一个线程+一个队列
redis 基于 reactor 模式开发了网络事件处理器,这个处理器叫做文件事件处理器,file event handler,这个文件事件处理器是单线程的,所以redis 是单线程的模型,采用 io多路复用机制同时监听多个 socket,根据socket上的事件来选择对应的事件处理器来处理这个事件。
文件事件处理器包含:多个 socket,io多路复用程序,文件事件分派器,事件处理器(命令请求处理器、命令恢复处理器、连接应答处理器)
文件事件处理器是单线程的,通过 io 多路复用机制监听多个 socket,实现高性能和线程模型简单性
被监听的 socket 准备好执行 accept,read,write,close等操作的时候,会产生对应的文件事件,调用之前关联好的时间处理器处理
多个 socket并发操作,产生不同的文件事件,i/o多路复用会监听多个socket,将这些 socket放入一个队列中排队。事件分派器从队列中取出socket给对应事件处理器。
一个socket时间处理完后,事件分派器才能从队列中拿到下一个socket,给对应事件处理器来处理。
文件事件:
AE_READABLE 对应 socket变得可读(客户端对redis执行 write操作)
AE_WRITABLE 对应 socket 变得可写(客户端对 redis执行 read操作)
I/O 多路复用可以同时监听AE_REABLE和 AE_WRITABLE ,如果同时达到则优先处理 AE_REABLE 时间
文件事件处理器:
连接应答处理器 对应 客户端要连接 redis
命令请求处理器 对应 客户端写数据到 redis
命令回复处理器 对应 客户端从 redis 读数据
流程:
一秒钟可以处理几万个请求
普通的 set,get kv缓存
类型 map结构,比如一个对象(没有嵌套对象)缓存到 redis里面,然后读写缓存的时候,可以直接操作hash的字段(比如把 age 改成 21,其他的不变)
key=150
value = {
}
有序列表 ,元素可以重复
可以通过 list 存储一些列表型数据结构,类似粉丝列表,文章评论列表。
例如:微信大 V的粉丝,可以以 list 的格式放在 redis 里去缓存
key=某大 V value=[zhangsan,lisi,wangwu]
比如 lrange 可以从某个元素开始读取多少个元素,可以基于 list 实现分页查询功能,基于 redis实现高性能分页,类似微博下来不断分页东西。
可以搞个简单的消息队列,从 list头怼进去(lpush),list尾巴出来 (brpop)
无序集合,自动去重
需要对一些数据快速全局去重,(当然也可以基于 HashSet,但是单机)
基于 set 玩差集、并集、交集的操作。比如:2 个人的粉丝列表整一个交集,看看 2 个人的共同好友是谁?
把 2 个大 V 的粉丝都放在 2 个 set中,对 2 个 set做交集(sinter)
排序的 set,去重但是可以排序,写进去的时候给一个分数,自动根据分数排序
排行榜:
zadd board score username
例如:
zadd board 85 zhangsan
zadd board 72 wangwu
zadd board 96 lis
zadd board 62 zhaoliu
自动排序为:
96 lisi
85 zhangsan
72 wangwu
62 zhaoliu
获取排名前 3 的用户 : zrevrange board 0 3
96 lisi
85 zhangsan
72 wangwu
查看zhaoliu的排行 :zrank board zhaoliu 返回 4
内存是宝贵的,磁盘是廉价的
给key设置过期时间后,redis对这批key是定期删除+惰性删除
定期删除:
redis 默认每隔 100ms随机抽取一些设置了过期时间的 key,检查其是否过期了,如果过期就删除。
注意:redis是每隔100ms随机抽取一些 key来检查和删除,而不是遍历所有的设置过期时间的key(否则CPU 负载会很高,消耗在检查过期 key 上)
惰性删除:
获取某个key的时候, redis 会检查一下,这个key如果设置了过期时间那么是否过期,如果过期了则删除。
如果定期删除漏掉了许多过期key,然后你也没及时去查,也没走惰性删除,如果大量过期的key堆积在内存里,导致 redis 内存块耗尽,则走内存淘汰机制。
内存淘汰策略:
LRU 算法:
缓存架构(多级缓存架构、热点缓存)
redis 高并发瓶颈在单机,读写分离,一般是支撑读高并发,写请求少,也就 一秒一两千,大量请求读,一秒钟二十万次。
一主多从,主负责写,将数据同步复制到其他 slave节点,从节点负责读,所有读的请求全部走从节点。主要是解决读高并发。、
主从架构-读写分离-支撑10W+读QPS架构
master-slave 复制,是异步的
核心机制:
master持久化对主从架构的意义:
如果开启了主从架构,一定要开启 master node的持久化,不然 master宕机重启数据是空的,一经复制,slave的数据也丢了
主从复制原理:
第一次启动或者断开重连情况:
正常情况下:
master 来一条数据,就异步给 slave
全年 99.99%的时间,都是出于可用的状态,那么就可以称为高可用性
redis 高可用架构叫故障转移,failover,也可以叫做主备切换,切换的时间不可用,但是整体高可用。
sentinal node(哨兵)
作用:
quorum = 1 (代表哨兵最低个数可以尝试故障转移,选举执行的哨兵)
master 宕机,只有 S2 存活,因为 quorum =1 可以尝试故障转移,但是没达到 majority =2 (最低允许执行故障转移的哨兵存活数)的标准,无法执行故障转移
如果 M1 宕机了,S2,S3 认为 master宕机,选举一个执行故障转移,因为 3 个哨兵的 majority = 2,所以可以执行故障转移
丢数据:
解决方案:
sdown 主观宕机,哨兵觉得一个 master 宕机(ping 超过了 is-master-down-after-milliseconds毫秒数)
odown 客观宕机,quorum数量的哨兵都觉得 master宕机
哨兵互相感知通过 redis的 pub/sub系统,每隔 2 秒往同一个 channel里发消息(自己的 host,ip,runid),其他哨兵可以消费这个消息
以及同步交换master的监控信息。
哨兵确保其他slave修改master信息为新选举的master
当一个 master被认为 odown marjority哨兵都同意,那么某个哨兵会执行主备切换,选举一个slave成为master(考虑 1. 跟master断开连接的时长 2. slave 优先级 3.复制 offset 4. runid)
选举算法:
quorum 数量哨兵认为odown-选举一个哨兵切换-获得 majority哨兵的授权(quorum majority 需要 majority个哨兵授权,quorum = majority 需要 quorum 哨兵授权)
第一个选举出来的哨兵切换失败了,其他哨兵等待 failover-time之后,重新拿confiuration epoch做为新的version 切换,保证拿到最新配置,用于 configuration传播(通过 pu/sub消息机制,其他哨兵对比 version 新旧更新 master配置)
高并发:主从架构
高容量:Redis集群,支持每秒几十万的读写并发
高可用:主从+哨兵
持久化的意义在于故障恢复数据备份(到其他服务器)+故障恢复(遇到灾难,机房断电,电缆被切)
AOF 只有一个,Redis 中的数据是有一定限量的,内存大小是一定的,AOF 是存放写命令的,当大到一定的时候,AOF 做 rewrite 操作,就会基于当时 redis 内存中的数据,来重新构造一个更小的 AOF 文件,然后将旧的膨胀很大的文件给删掉,AOF 文件一直会被限制在和Redis内存中一样的数据。AOF同步间隔比 RDB 小,数据更完整
优点:
缺点:
AOF 存放的指令日志,数据恢复的时候,需要回放执行所有指令日志,RDB 就是一份数据文件,直接加载到内存中。
优点:
缺点:
AOF 来保证数据不丢失,RDB 做不同时间的冷备
支持 N 个 Redis master node,每个 master node挂载多个 slave node
多master + 读写分离 + 高可用
数据量很少,高并发 - replication + sentinal 集群
海量数据 + 高并发 + 高可用 - redis cluster
hash算法-一致性 hash 算法- redis cluster-hash slot算法
redis cluster :自动对数据进行分片,每个 master 上放一部分数据,提供内置的高可用支持,部分master不可用时,还是可以继续工作
cluster bus 通过 16379进行通信,故障检测,配置更新,故障转移授权,另外一种二进制协议,主要用于节点间进行高效数据交换,占用更少的网络带宽和处理时间
key进行hash,然后对节点数量取模,最大问题只有任意一个 master 宕机,大量数据就要根据新的节点数取模,会导致大量缓存失效。
key进行hash,对应圆环上一个点,顺时针寻找距离最近的一个点。保证任何一个 master 宕机,只受 master 宕机那台影响,其他节点不受影响,此时会瞬间去查数据库。
缓存热点问题:
可能集中在某个 hash区间内的值特别多,那么会导致大量的数据都涌入同一个 master 内,造成 master的热点问题,性能出现瓶颈。
解决方法:
给每个 master 都做了均匀分布的虚拟节点,这样每个区间内大量数据都会均匀的分布到不同节点内,而不是顺时针全部涌入到同一个节点中。
redis cluster 有固定 16384 个 hash slot,对每个key计算 CRC16 值,然后对16384取模,可以获取 key对应的 hash slot
redis cluster 中每个 master 都会持有部分 slot ,当一台 master 宕机时候,会最快速度迁移 hash slot到可用的机器上(只会短暂的访问不到)
走同一个 hash slot 通过 hash tag实现
集群元数据:包括 hashslot-node之间的映射表关系,master-slave之间的关系,故障的信息
集群元数据集中式存储(storm),底层基于zookeeper(分布式协调中间件)集群所有元数据的维护。好处:元数据的更新和读取,时效性好,一旦变更,其他节点立刻可以感知。缺点:所有元数据的更新压力全部集中在一个地方,可能会导致元数据的存储有压力。
goosip: 好处:元数据的更新比较分散,有一定的延时,降低了压力。缺点:更新有延时,集群的一些操作会滞后。(reshared操作时configuration error)
自己提供服务的端口号+ 10000 ,每隔一段时间就会往另外几个节点发送ping消息,同时其他几点接收到ping之后返回pong
故障信息,节点的增加和移除, hash slot 信息
meet:某个节点发送 meet给新加入的节点,让新节点加入集群中,然后新节点就会开始于其他节点进行通信
ping:每个节点都会频繁给其他节点发送ping,其中包含自己的状态还有自己维护的集群元数据,互相通过ping交换元数据
ping:返回ping和meet,包含自己的状态和其他信息
fail:某个节点判断另一个节点fail之后,就发送 fail 给其他节点,通知其他节点,指定的节点宕机了
ping 很频繁,且携带元数据,会加重网络负担
每个节点每秒会执行 10 次 ping,每次选择 5 个最久没有通信的其他节点
当如果发现某个节点通信延迟达到了 cluster_node_timeout /2 ,那么立即发送 ping, 避免数据交换延迟过长,落后时间太长(2 个节点之间 10 分钟没有交换数据,整个集群处于严重的元数据不一致的情况)。
每次ping,一个是带上自己的节点信息,还有就是带上1/10其他节点的信息,发送出去,进行数据交换
至少包含 3 个其他节点信息,最多包含总节点-2 个其他节点的信息
客户端发送到任意一个redis实例发送命令,每个redis实例接受到命令后,都会计算key对应的hash slot,如果在本地就本地处理,否则返回moved给客户端,让客户端进行重定向 (redis-cli -c)
通过tag指定key对应的slot,同一个 tag 下的 key,都会在一个 hash slot中,比如 set key1:{100} 和 set key2:{100}
本地维护一份hashslot-node的映射表。
JedisCluster 初始化的时候,随机选择一个 node,初始化 hashslot-node 映射表,同时为每个节点创建一个JedisPool连接池,每次基于JedisCluster执行操作,首先JedisCluster都会在本地计算key的hashslot,然后再本地映射表中找到对应的节点,如果发现对应的节点返回moved,那么利用该节点的元数据,更新 hashslot-node映射表(重试超过 5 次报错)
hash slot正在迁移,那么会返回ask 重定向给jedis,jedis 接受到ask重定向之后,,会重定向到目标节点去执行
判断节点宕机:
如果一个节点认为另外一个节点宕机了, 就是pfail,主观宕机
如果多个节点都认为另外一个节点宕机了,那么就是fail,客观宕机(跟哨兵原理一样)
在cluster-node-timeout内,某个节点一直没有返回 pong,那么就被认为是 pfail
如果一个节点认为某个节点pfail了,那么会在gossip消息中,ping给其他节点,如果超过半数的节点认为pfail了,那么就会变成fail。
从节点过滤:
对宕机的 mster node ,从其所有的 slave node中,选择一个切换成 master node
检查每个 slave node与master node断开连接的时间,如果超过了cluster-node-timeout * cluster-slave-validity-factor,那么就没资格切换成 master(和哨兵一致)
从节点选举:
每个从节点,根据自己对 master 复制数据的 offset,设置一个选举时间,offset越大(复制数据越多)的从节点,选举时间越靠前,所有的 master node 开始投票,给要进行选举的 slave进行投票,如果大部分 master node(N/2 +1) 都投票给某个从节点,那么选举通过,从节点执行主备切换,从节点切换成主节点
总结:和哨兵很像,直接集成了 replication 和 sentinal
方案:
事前:保证 redis 集群高可用性 (主从+哨兵或 redis cluster),避免全盘崩溃
事中:本地 ehcache 缓存 + hystrix 限流(保护数据库) 降级,避免 MySQL被打死
事后: redis持久化,快速恢复缓存数据,继续分流高并发请求
限制组件每秒就 2000 个请求通过限流组件进入数据库,剩余的 3000 个请求走降级,返回一些默认 的值,或者友情提示
好处 :
4000 个请求黑客攻击请求数据库里没有的数据
解决方案:把黑客查数据库中不存在的数据的值,写到缓存中,比如: set -999 UNKNOWN
读的时候,先读缓存,缓存没有,就读数据库,然后取出数据后放入缓存,同时返回响应
更新的时候,删除缓存,更新数据库
为什么不更新缓存:
更新缓存代价太高(更新 20 次,只读 1 次),lazy思想,需要的时候再计算,不需要的时候不计算
方案:先删除缓存,再修改数据库
方案:写,读路由到相同的一个内存队列(唯一标识,hash,取模)里,更新和读操作进行串行化(后台线程异步执行队列串行化操作),(队列里只放一个更新查询操作即可,多余的过滤掉,内存队列里没有该数据更新操作,直接返回 )有该数据更新操作则轮询取缓存值,超时取不到缓存值,直接取一次数据库的旧值
TP 99 意思是99%的请求可以在200ms内返回
注意点:多个商品的更新操作都积压在一个队列里面(太多操作积压只能增加机器),导致读请求发生大量的超时,导致大量的读请求走数据库
一秒 500 写操作,每200ms,100 个写操作,20 个内存队列,每个队列积压 5 个写操作,一般在20ms完成
方案:分布式锁 + 时间戳比较
10台机器,5 主 5 从,每个节点QPS 5W ,一共 25W QPS(Redis cluster 32G + 8 核 ,Redis 进程不超过 10G)总内存 50g,每条数据10kb,10W 条数据1g,200W 条数据 20G,占用总内存不到50%,目前高峰期 3500 QPS
作者: mousycoder
redis 内部使用文件事件处理器 file event handler,这个文件事件处理器是单线程的,所以 redis 才叫做单线程的模型。它采用 IO 多路复用机制同时监听多个 socket,根据 socket 上的事件来选择对应的事件处理器进行处理。
文件事件处理器的结构包含 4 个部分:
多个 socket
IO 多路复用程序
文件事件分派器
事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
多个 socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是 IO 多路复用程序会监听多个 socket,会将 socket 产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理。
1. 充分利用CPU资源
现在世界上大多数计算机只有一块CPU.因此,充分利用CPU资源显得尤为重要。当执行单线程程序时,由于在程序发生阻塞时CPU可能会处于空闲状态。这将造成大量的计算资源的浪费。而在程序中使用多线程可以在某一个线程处于休眠或阻塞时,而CPU又恰好处于空闲状态时来运行其他的线程。这样CPU就很难有空闲的时候。因此,CPU资源就得到了充分地利用。
2. 简化编程模型
如果程序只完成一项任务,那只要写一个单线程的程序,并且按着执行这个任务的步骤编写代码即可。但要完成多项任务,如果还使用单线程的话,那就得在在程序中判断每项任务是否应该执行以及什么时候执行。如显示一个时钟的时、分、秒三个指针。使用单线程就得在循环中逐一判断这三个指针的转动时间和角度。如果使用三个线程分另来处理这三个指针的显示,那么对于每个线程来说就是指行一个单独的任务。这样有助于开发人员对程序的理解和维护。
3. 简化异步事件的处理
当一个服务器应用程序在接收不同的客户端连接时最简单地处理方法就是为每一个客户端连接建立一个线程。然后监听线程仍然负责监听来自客户端的请求。如果这种应用程序采用单线程来处理,当监听线程接收到一个客户端请求后,开始读取客户端发来的数据,在读完数据后,read方法处于阻塞状态,也就是说,这个线程将无法再监听客户端请求了。而要想在单线程中处理多个客户端请求,就必须使用非阻塞的Socket连接和异步I/O.但使用异步I/O方式比使用同步I/O更难以控制,也更容易出错。因此,使用多线程和同步I/O可以更容易地处理类似于多请求的异步事件。
4. 使GUI更有效率
使用单线程来处理GUI事件时,必须使用循环来对随时可能发生的GUI事件进行扫描,在循环内部除了扫描GUI事件外,还得来执行其他的程序代码。如果这些代码太长,那么GUI事件就会被“冻结”,直到这些代码被执行完为止。
在现代的GUI框架(如SWING、AWT和SWT)中都使用了一个单独的事件分派线程(event dispatch thread,EDT)来对GUI事件进行扫描。当我们按下一个按钮时,按钮的单击事件函数会在这个事件分派线程中被调用。由于EDT的任务只是对GUI事件进行扫描,因此,这种方式对事件的反映是非常快的。
5. 节约成本
提高程序的执行效率一般有三种方法:
(1)增加计算机的CPU个数。
(2)为一个程序启动多个进程
(3)在程序中使用多进程。
第一种方法是最容易做到的,但同时也是最昂贵的。这种方法不需要修改程序,从理论上说,任何程序都可以使用这种方法来提高执行效率。第二种方法虽然不用购买新的硬件,但这种方式不容易共享数据,如果这个程序要完成的任务需要必须要共享数据的话,这种方式就不太方便,而且启动多个线程会消耗大量的系统资源。第三种方法恰好弥补了第一种方法的缺点,而又继承了它们的优点。也就是说,既不需要购买CPU,也不会因为启太多的线程而占用大量的系统资源(在默认情况下,一个线程所占的内存空间要远比一个进程所占的内存空间小得多),并且多线程可以模拟多块CPU的运行方式,因此,使用多线程是提高程序执行效率的最廉价的方式。
1. 事件管理流程负责人
事件管理流程负责人是事件管理解决方案的责任人,承担事件管理解决方案结果的责任。同时拥有相应的权限。其从宏观上监控流程,确保事件管理流程在IT服务组织的范围内被正确的执行。当流程不能够适应IT服务组织的运作时,流程负责人必须及时地对此进行分析、找出缺陷、进行改进,从而实现可持续提高。
1.1 职责:
确定管理流程的衡量指标;
确保事件流程能够取得管理层的参与和支持;
确保事件流程符合公司实际状况和公司 IT发展战略;
总体上管理和监控流程,建立事件流程实施、评估和持续优化机制;
确保事件流程实用、有效、正确地执行,当流程不能够适应公司的情况时,必须及时的对此进行分析、找出缺陷、进行改进(假如增加或合并流程的角色),从而实现可持续提高;
保持与其他流程负责人的定期沟通;
1.2 技能要求:
深刻理解事件管理流程;
充分理解其他IT服务流程,能够进行流程接口设计;
能够很好地理解业务对于事件管理的需求;
对质量控制与保障有很深入的了解;
有决策权,能够确保事件管理流程设计要求在实施项目中得到贯彻和执行;
具有很好的沟通技能,能够取得公司高层的支持,获得所需资源。
2. 事件经理
事件经理负责事件解决过程中的协调和监控,以及事件升级的判断以及具体执行。实际工作中,由于事件与问题的解决思路前者重“快”,后者重“因”,因此并不建议事件经理与问题经理由同一人兼任。事件经理受困于繁多的事件,相对难以静心下来进行问题的寻因与解决。
2.1 职责:
负责对事件的解决协调资源,保证故障的最终排除;
控制事件管理流程的高效性和有效性,当事件优先级为紧急或者事件将超过规定的时限,负责按照升级方法对事件进行处理确保有效协调资源,促进支持工程师快速恢复正常服务;
确保和问题经理的有效合作;
确保正确和广泛地收集和分析事件数据,发现IT和业务相关的问题;
2.2 技能要求:
了解技术架构和技术环境;
较强的口头表达能力和与用户沟通技巧;
处理纠纷的能力;
深刻了解事件管理流程;
较强的领导能力;
3. 服务台人员
服务台人员负责接收各个渠道提交的所有的事件,对事件进行初步的处理,并根据实际情况将事件分派到合适的二线支持工程师或者三线支持工程师。
3.1 职责:
在指定的响应时间内响应所有服务台热线电话、邮件、传真等事件的报告;
完整记录所有接收的事件信息,包括:记录事件报
this.style.border = '1px solid white';};} var all2 = document.getElementsByTagName('div')[1].getElementsByTagName('*'); for (var i = 0, n = all2.length; i n; ++i){ all2[i].onmouseover = function(e){ this.style.border = '1px solid red'; if (e) //停止事件冒泡 e.stopPropagation();elsewindow.event.cancelBubble = true; log.value = '鼠标现在进入的是: ' + this.nodeName;};all2[i].onmouseout = function(e){ this.style.border = '1px solid white';};}}window.onload = init;//]]/script/headbodyh1Bubble in JavaScript DOM/h1 pDOM树的结构是:/p precodeUL- LI- A- SPAN/code/predivullia href="#"spanBubbllllllllllllllle/span/a/li lia href="#"spanBubbllllllllllllllle/span/a/li/ul/divtextarea/textarea p鼠标进入UL的任何一个子元素,如果不停止冒泡,我们从UL到SPAN都定义了鼠标悬停(codemouseover/code)事件,这个事件会上升了UL,从而从鼠标所进入的元素到UL元素都会有红色的边。/pdivullia href="#"spanBubbllllllllllllllle/span/a/li lia href="#"spanBubbllllllllllllllle/span/a/li/ul/divp如果停止冒泡,事件不会上升,我们就可以获取精确的鼠标进入元素。/p/body/html 从上面的例子可知道当你触发任何一个元素的事件时浏览器默认从该元素向上父元素上之一迭代冒泡的出发具有该事件的父元素,直到包含该元素的最大父元素为止。如果想阻止这样的情况发生,例如,我只想让某个元素执行moveover事件,不想让保护她的父元素执行,就需调用js的阻止函数e.stopPropagation()或者window.event.cancelBubble = true; 这两个方法的意思是: event.preventDefault() 该方法将通知 Web 浏览器不要执行与事件关联的默认动作(如果存在这样的动作)。例如,如果 type 属性是 "submit",在事件传播的任意阶段可以调用任意的事件句柄,通过调用该方法,可以阻止提交表单。注意,如果 Event 对象的 cancelable 属性是 fasle,那么就没有默认动作,或者不能阻止默认动作。无论哪种情况,调用该方法都没有作用。 event.stopPropagation() 该方法将停止事件的传播,阻止它被分派到其他 Document 节点。在事件传播的任何阶段都可以调用它。注意,虽然该方法不能阻止同一个 Document 节点上的其他事件句柄被调用,但是它可以阻止把事件分派到其他节点。
发表评论
暂时没有评论,来抢沙发吧~