皮皮网

皮皮网

【双端游源码】【ip纪录源码】【espace mobile源码】dubbo netty 源码

时间:2024-11-30 03:41:40 分类:时尚

1.一次 Netty 代码不健壮导致的源码大量 CLOSE_WAIT 连接原因分析
2.Dubbo源码解析:网络通信
3.dubbo十层架构?
4.Netty的实现原理、特点与优势、源码以及适用场景
5.Java教程:dubbo源码解析-网络通信

dubbo netty 源码

一次 Netty 代码不健壮导致的源码大量 CLOSE_WAIT 连接原因分析

       我们线上存在一个 Dubbo 服务,遇到大量 CLOSE_WAIT 状态的源码连接,始终无法消失,源码因此进行了原因分析。源码双端游源码

       CLOSE_WAIT 状态出现在被动关闭方,源码收到对端 FIN 包后回复 ACK,源码但未发送 FIN 包之前。源码问题在于服务没有回复 FIN,源码原因可能是源码收到了 FIN 包却未发送响应,通过抓包验证了这一情况。源码

       问题核心在于为什么没有回复 FIN。源码Dubbo 服务底层使用 Netty,源码作为普通的源码 TCP 服务端,关键在于 FIN 包的回复。

       分析显示,如果服务没有发送 FIN 包,可能原因有:

       1. 半连接队列或全连接队列积压,通过 ss 命令查看全连接队列大小和等待 accept 的连接个数。

       2. LISTEN 状态的 socket,Recv-Q 表示等待用户进程 accept 的连接个数,Send-Q 表示全连接队列最大容纳的连接数。

       非 LISTEN 状态的 socket,Recv-Q 表示 receive queue 字节大小,Send-Q 表示 send queue 字节大小。

       通过 ss 命令确认 Recv-Q 为 0,全连接队列无积压。

       嫌疑指向 Netty 没有注册事件,导致收到 FIN 包后无动于衷。

       进一步发现,凌晨 1 点业务实例加载大量数据导致堆内存占满,持续进行 fullgc。Netty 线程出现 OOM 异常。在 org.jboss.netty.channel.socket.nio.NioServerBoss#process 方法中,Netty 调用 accept 取走连接,第 行尝试注册事件时抛出 java.lang.OutOfMemoryError 异常。

       因此,Netty 处理不健壮,try-catch 包裹了 accept 连接和注册事件逻辑,在 OOM 异常处理时,未能成功注册事件或关闭连接,导致连接存在但不被监听处理。

       推荐相关视频学习:

       LinuxC++零拷贝的实现 用户态协议栈 ntytcp

       支撑互联网的基石 TCP/IP,5个方面全面解析

       TCP/IP协议栈深度解析丨实现单机百万连接丨优化三次握手、四次挥手

       LinuxC++后台服务器开发架构师免费学习地址

       为模拟问题复现,可使用字节码注入或直接重构 Netty 源码。本地拥有 Netty 源码,采用重构方法更快。重新构建项目后,使用 nc 模拟健康检查握手并断开连接,CLOSE_WAIT 状态连接持续存在直至 Netty 进程退出。再次 nc 断开连接,新增 CLOSE_WAIT 状态。由于服务持续进行健康检查,导致 OOM 期间 CLOSE_WAIT 状态不断增加。

       问题核心:Netty 代码不够健壮,尝试捕获异常时,未能正确处理连接注册事件或关闭连接,ip纪录源码导致连接存在且未被监听。

       修改方式:在 catch 处理 throwable 时关闭连接即可,最新版本的 Netty 代码这部分逻辑已优化,将 accept 和注册事件拆分。有兴趣的读者可以尝试。

       学习 TCP、网络编程是解决类似问题的关键。

Dubbo源码解析:网络通信

       <dubbo源码解析:深入理解网络通信

       在之前的章节中,我们已经了解了消费者如何通过服务发现和负载均衡机制找到提供者并进行远程调用。本章将重点解析网络通信的实现细节。

       网络通信主要在Dubbo的Remoting模块中进行,涉及多种通信协议,包括dubbo协议、RMI、Hessian、HTTP、WebService、Thrift、REST、gRPC、Memcached和Redis等。每个协议都有其特定的优缺点,如Dubbo协议适用于高并发场景,而RMI则使用标准JDK序列化。

       Dubbo的序列化机制支持多种方式,如Hessian2、Kryo、FST等。近年来,高效序列化技术如Kryo和FST的出现,可提升性能,只需在配置中简单添加即可优化。

       关于数据格式和粘包拆包问题,Dubbo采用私有RPC协议,消息头存储元信息,如魔法数和数据类型,消息体则包含调用信息。消费者发送请求时,会通过MockClusterInvoker封装服务降级逻辑,然后通过序列化转换为网络可传输的数据格式。

       服务提供方接收请求时,首先对数据包进行解码,确认其格式正确性,然后调用服务逻辑。提供方返回调用结果时,同样经过序列化和编码,最后通过NettyChannel发送给消费者。

       在心跳检测方面,Dubbo采用双向心跳机制,客户端和服务端定期发送心跳请求以维持连接。此外,还通过定时任务处理重连和断连,确保连接的稳定性和可靠性。

       总的来说,Dubbo的网络通信模块精细且灵活,通过多种协议和优化技术确保服务调用的高效和可靠性。

dubbo十层架构?

       Dubbo简介

       Dubbo是Alibaba开源的分布式服务框架,它按照分层的espace mobile源码方式来架构,使用这种方式可以使各层解耦。

       Dubbo在调用远程的服务的时候再本地有一个接口,就想调用本地方法一样去调用,底层实现好参数传输和远程服务运行结果传回之后的返回。

       Dubbo的特点:

       (1)它主要使用高效的网络框架和序列化框架,让分布式服务之间调用效率更高。

       (2)采用注册中心管理众多的服务接口地址,当你想调用服务的时候只需要跟注册中心询问谈歼瞎即可,不像使用WebService一样每个服务都得记录好接口调用方式。

       (3)监控中心时实现服务方和调用方之间运行状态的监控,还能控制服务的优先级、权限、权重、上下线等,让整个庞大的分布式服务系统的维护和治理比较方便。

       (4)高可用,如果有服务挂了,注册中心就会从服务列表去掉该节点,客户端会像注册中心请求另一台可用的服务节点重新调用。同时注册中心也能实现高可用(ZooKeeper)。

       (5)负载均衡,采用软负载均衡算法实现对多个相同服务的节点的请求负载均衡。

       Dubbo需要四大基本组件:Rigistry,Monitor,Provider,Consumer。

       1、含空监控中心的配置文件-dubbo.properties文件

       (1)容器改改,监控中心是在jetty和spring环境下运行,依赖于注册中心,日志系统是log4j

dubbo.container=log4j,spring,registry,jetty

       (2)监控服务的名称,监控系统对整个Dubbo服务系统来说也是一个服务

dubbo.application.name=simple-monitor

       (3)服务的所有者,这是Dubbbo的服务的功能,可以指定服务的负责人

dubbo.application.owner=coselding

       (4)注册中心的地址,配置后监控中心就能通过注册中心获取当前可用的服务列表及其状态,在页面向你汇报Dubbo中的服务运行情况。

dubbo.registr.address=multicast://{ ip}:{ port}//广播

       dubbo.registr.address=zookeeper://{ ip}:{ port}//zookeper

       dubbo.registr.address=redis://{ ip}:{ port}//redis

       dubbo.registr.address=dubbo://{ ip}:{ port}//dubbo

       (5)dubbo协议端口号

dubbo.protocol.port=

       (6)jetty工作端口号

dubbo.jetty.port=

       (7)工作目录,用于存放监控中心的数据

dubbo.jetty.directory=${ user.home}/monitor

       (8)监控中心报表存放目录

       dubbo.charts.directory=${ dubbo.jetty.directory}/charts

       (9)监控中心数据资料目录

       dubbo.statistics.directory=${ user.home}/monitor/statistics

       ()监控中心日志文件路径

       dubbo.log4j.file=logs/dubbo-monitor-simple.log

       ()监控中心日志记录级别

       dubbo.log4j.level=WARN

       2、Dubbo提供负载均衡方式

       (1)Random,随机,按权重配置随机概率,调用量越大分布越均匀,默认方式。

       (2)RounRobin,轮询,按权重设置轮询比例,如果存在比较慢的机器容易在这台机器上请求阻塞较多。

       (3)LeastActive,最少活跃调用数,不支持权重,只能根据自动识别的活跃数分配,不能灵活调配。

       (4)ConsistenHash,一致性hash,对相同参数的请求路由到一个服务提供者上,如果有类似灰度发布需求可采用。

       3、Dubbo过滤器

       Dubbo初始化过程加载ClassPath下的META-INF/dubbo/internal/,META-INF/dubbo/,META-INF/services/三个路径下的com.alibaba.dubbo.rpc.Filter文件。文件内容:

Name=FullClassName,rsi 威廉源码这些类必须实现Filter接口。

       自定义Filter类:

       配置文件在配置过滤器,consumer.xml中:

       Dubbo对过滤器的加载过程:

先加载三个路径下的com.alibaba.dubbo.rpc.Filter文件里面的键值对,key为过滤器名称,value为过滤器的类的全限定名(这个类必须实现Dubbo中的Filter接口)。

自定义的类中@Active注解是过滤器设定的全局基本属性。

Spring在加载consumer.xml文件时,通过dubbo:consumerfilter="xxx"id="xxx"retrries="0"这个配置指定消费者端要加载的过滤器,通过filter属性指定过滤器名称。

       @Activate注解-自动激活,group属性是表示匹配了对应的角色才被加载,value表示表明过滤条件,不写则表示所有条件都会被加载,写了则只有dubboURL中包含该参数名且参数值不为空才被加载,这个参数会以dubbo协议的一个参数K-V对传到Provider。

       4、Dubbo的Provider配置

       5、Dubbo的Consumer配置

       1、Dubbo是什么?

       Dubbo是阿里巴巴开源的基于Java的高性能RPC分布式框架。

       2、为什么使用Dubbo?

       很多公司都在使用,经过很多线上的考验,内部使用了Netty,Zookeeper,保证了高性能可用性。

       使用Dubbo可以将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,可以提高业务复用灵活性扩展,使前端应用能快速的响应对边的市场需求。分布式架构可以承受更大规模的并发流量。

       Dubbo的服务治理图:

       3、Dubbo和SpringCloud的区别

       两个没有关联,但是非要说区别,有如下几点:

       (1)通信方式不同,Dubbo使用RPC通信,SpringCloud使用HTTPRestful方式

       (2)组成部分不同

       4、Dubbo支持的协议

       dubbo://?(推荐);rmi://;hessian://;.weidian.dubbo.IMyDemo"version="1.0"id="myDemo"url="dubbo://.0.0.1:/"/dubbo:reference

       、Dubbo多协议

       Dubbo允许配置多协议,在不同服务器上支持不同协议,或者同一服务支持多种协议。

       、当一个服务有多种实现时怎么做?

       当一个接口有多种是现实,可以用group属性来分组,服务提供方和消费方都指定同一个group即可。

       、兼容旧版本

       使用版本号过度,多个不同版本的服务注册到注册中心,版本号不同的服务相互间不引用。

       、Dubbo可以缓存吗?

       Dubbo提供声明式缓存,用于加速热门数据的访问速度,以减少用户加缓存的工作量。

       、Dubbo服务之间的调用时阻塞的吗?

       默认是同步等待结果阻塞的,支持异步调用。Dubbo是基于NIO的非阻塞实现并行调用的,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小,房产html 源码异步调用会返回一个Future对象。

       、Dubbo不支持分布式事务

       、Dubbo必须依赖的包

       Dubbo必须依赖JDK,其他为可选。

       、Dubbo使用过程中的问题

       Dubbo的设计目的是为了满足高并发小数据量的rpc请求,在大数据量下性能表现不是很好,建议使用rmi或.alibaba.boot/groupId

artifactIddubbo-spring-boot-starter/artifactId

version0.1.0/version

       /dependency

       !----

       dependency

groupIdcom.tec/groupId

artifactIdzkclient/artifactId

version0./version

       /dependency

       (2)配置dubbo

       ##Dubbo服务提供者配置

       spring.dubbo.application.name=provider

       spring.dubbo.registry.address=zookeeper://.0.0.1:

       spring.dubbo.protocol.name=dubbo

       spring.dubbo.protocol.port=

       spring.dubbo.scan=org.spring.springboot.dubbo

       ##Dubbo服务消费者配置

       spring.dubbo.application.name=consumer

       spring.dubbo.registry.address=zookeeper://.0.0.1:

       spring.dubbo.scan=org.spring.springboot.dubbo

Dubbo分布式服务框架介绍

       随着业务的发展、用户量的增长、系统并发访问需求越来越大,系统数量增多,调用依赖关系也变得复杂,为了确保系统高可用、高并发的要求,系统的架构也从单体时代慢慢迁移至服务SOA时代,根据不同服务对系统资源的要求不同,我们可以更合理的配置系统资源,使系统资源利用率最大化。而Dubbo则是SOA服务化治理方案的一个核心框架。

       Dubbo作为阿里巴巴内部的SOA服务化治理方案的核心框架,在年时已经每天为+个服务提供3,,,+次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。Dubbo自年开源后,已被许多肢启知非阿里系公司使用,其中既有当当网、网易考拉等互联网公司,也有中国人寿、青岛海尔等传统企业。

       Dubbo是一个高性能服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案,使得应用可通过高性能RPC实现服务的输出和输入功能,和Spring框架可以无缝集成。

       作为一个分布式服务框架,以及SOA治理方案,Dubbo其功能主要包括:

       Dubbo最大的特点是按照分层架构思维构建应用服务,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色。

       Dubbo包含远程通讯、服务集群和服务发现与注册三个核心部分。提供透明化的远程方法调用,实现像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。同时具备软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。可以实现服旁则务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。

       Dubbo服务组件调用关秕说明:

       Dubbo框架设计一共划分了个层,而最上面的Service层是留给实际想要使用Dubbo开发分布式服务的开发者实现业务逻辑的接口层。图中左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为历消双方都用到的接口。

       下面,结合Dubbo官方文档,我们分别理解一下框架分层架构中,各个层次的设计要点:

       从上图可以看出,Dubbo对于服务提供方和服务消费方,从框架的层中分别提供了各自需要关心和扩展的接口,构建整个服务生态系统(服务提供方和服务消费方本身就是一个以服务为中心的)。

       根据官方提供的,对于上述各层之间关系的描述,如下所示:

       说说Dubbo的分层?

       从?的范围来说,dubbo分为三层,

       business业务逻辑层由我们?来提供接?和实现还有?些配置信息;

       RPC层就是真正的RPC调?的核?层,封装整个RPC的调?过程、负载均衡、集群容错、代理,

       remoting则是对?络传输协议和数据转换的封装。划分到更细的层?,就是图中的层模式,整个分层依赖由上?下,除开business业务逻辑之外,其他的?层都是SPI机制。

如何更好地学习dubbo源代码

       一、Dubbo整体架构

       1、Dubbo与Spring的整合

       Dubbo在使用上可以做到非常简单,不管是Provider还是Consumer都可以通过Spring的配置文件进行配置,配置完之后,就可以像使用

       springbean一样进行服务暴露和调用了,完全看不到dubbo

       api的存在。这是因为dubbo使用了spring提供的可扩展Schema自定义配置支持。在spring配置文件中,可以像、这样进行配置。

       META-INF下的spring.handlers文件中指定了dubbo的xml解析类:DubboNamespaceHandler。像前面的被解

       析成ServiceConfig,被解析成ReferenceConfig等等。

       2、jdkspi扩展

       由于Dubbo是开源框架,必须要提供很多的可扩展点。Dubbo是通过扩展jdk

       spi机制来实现可扩展的。具体来说,就是在META-INF目录下,放置文件名为接口全称,文件中为key、value键值对,value为具体实现类

       的全类名,key为标志值。由于dubbo使用了url总线的设计,即很多参数通过URL对象来传递,在实际中,具唯睁体要用到哪个值,可以通过url中的参

       数值来指定。

       Dubbo对spi的扩展是通过ExtensionLoader来实现的,查看ExtensionLoader的源码,可以看到Dubbo对jdkspi做了三个方面的扩展:

       (1)jdkspi仅仅通过接口类名获取所有实现,而ExtensionLoader则通过接口类名和key值获取一个实现;

       (2)Adaptive实现,就是生成一个代理类,这样搭燃就可以根据实际调用时的一些参数动态决定要调用的类了。

       (3)自动包装实现,这种实现的类一般是自动激活的,常用于包装类,比如Protocol的两个实现类:ProtocolFilterWrapper、ProtocolListenerWrapper。

       3、url总线设计

       Dubbo为了使得各层解耦,采用了url总线的设计。我们通常的设计会把层与层之间的交互参数做成Model,这样层与层之间沟通成本比较大,扩展起来

       也比较麻烦。因此,Dubbo把各层之间的通信都采用url的形式。比如,注册中心启动时,参数的url为:

       registry://0.0.0.0:?codec=registrytransporter=netty

       这就表示当前是注册中知山虚心,绑定到所有ip,端口是,解析器类型是registry,使用的底层网络通信框架是netty。

       二、Dubbo启动过程

       Dubbo分为注册中心、服务提供者(provider)、服务消费者(consumer)三个部分。

       1、注册中心启动过程

       注册中心的启动过程,主要看两个类:RegistrySynchronizer、RegistryReceiver,两个类的初始化方法都是start。

       RegistrySynchronizer的start方法:

       (1)把所有配置信息load到内存;

       (2)把当前注册中心信息保存到数据库;

       (3)启动5个定时器。

       5个定时器的功能是:

       (1)AutoRedirectTask,自动重定向定时器。默认1小时运行1次。如果当前注册中心的连接数高于平均值的1.2倍,则将多出来的连接数重定向到其他注册中心上,以达到注册中心集群的连接数均衡。

       (2)DirtyCheckTask,脏数据检查定时器。作用是:分别检查缓存provider、数据库provider、缓存consumer、数据库

       consumer的数据,清除脏数据;清理不存活的provider和consumer数据;对于缓存中的存在的provider或consumer而数

       据库不存在,重新注册和订阅。

       (3)ChangedClearTask,changes变更表的定时清理任务。作用是读取changes表,清除过期数据。

       (4)AlivedCheckTask,注册中心存活状态定时检查,会定时更新registries表的expire字段,用以判断注册中心的存活状态。如果有新的注册中心,发送同步消息,将当前所有注册中心的地址通知到所有客户端。

       (5)ChangedCheckTask,变更检查定时器。检查changes表的变更,检查类型包括:参数覆盖变更、路由变更、服务消费者变更、权重变更、负载均衡变更。

       RegistryReceiver的start方法:启动注册中心服务。默认使用netty框架,绑定本机的端口。最后启动服务的过

Netty的实现原理、特点与优势、以及适用场景

       Netty是一个强大的Java NIO框架,它的主要优势在于简单性、健壮性、高性能、功能丰富、可定制性和可扩展性。它在业界已经得到了广泛的应用和验证,如Hadoop的RPC框架Avro、RocketMQ和Dubbox等。

       选择Netty的原因是它能够简化Socket通信的复杂性,减少编码和性能优化的负担。Netty框架通过提供简单易用的API,从网络处理代码中解耦业务逻辑,使得开发者能够专注于业务功能的实现。Netty基于NIO实现,其异步特性使得它能够高效处理并发请求,提高系统的响应速度。

       Netty的主要特点包括:异步事件驱动架构,强大的API抽象,丰富的组件支持,如Bootstrap、Channel、ChannelPipeline等,以及对多种协议的支持。通过这些特点,Netty能够灵活构建各种网络应用,无论是客户端还是服务器端。

       Netty适用于高性能、高并发的网络通信场景,如分布式系统中的远程服务调用、游戏服务器间通信、大数据领域的实时通信等。在实际应用中,Netty通常作为高性能通信的基础组件,与RPC框架、协议栈定制、大数据组件等紧密集成。

       在学习和使用Netty时,需要先掌握NIO相关知识,以便更好地理解和使用Netty的源码。Netty的核心组件包括Bootstrap、Channel、ChannelPipeline、ChannelInboundHandler和ChannelInitializer等,它们共同协作以构建和管理网络通信。

       Netty的应用场景广泛,包括互联网行业中的分布式服务通信、游戏行业中的高性能网络通信、大数据领域的实时通信等。通过学习Netty的原理、特点和优势,开发者能够构建高效、可扩展的网络应用,并在实际项目中发挥重要作用。

       学习Netty的过程中,除了掌握其核心原理和组件,还需注意一些关键点,如线程管理、数据处理、协议设计等。了解Netty的面试题和学习资源也是提升技能的有效途径,这有助于深入理解Netty的用法和最佳实践。

       总之,Netty是一个功能强大、易于使用的网络通信框架,其异步事件驱动架构、强大的API抽象和丰富的组件支持使其成为构建高性能网络应用的理想选择。通过掌握Netty的基本原理和应用场景,开发者能够有效提升网络通信系统的性能和可靠性。

Java教程:dubbo源码解析-网络通信

       在之前的内容中,我们探讨了消费者端服务发现与提供者端服务暴露的相关内容,同时了解到消费者端通过内置的负载均衡算法获取合适的调用invoker进行远程调用。接下来,我们聚焦于远程调用过程,即网络通信的细节。

       网络通信位于Remoting模块中,支持多种通信协议,包括但不限于:dubbo协议、rmi协议、hessian协议、ty进行网络通讯,NettyClient.doOpen()方法中可以看到Netty的相关类。序列化接口包括但不限于:Serialization接口、Hessian2Serialization接口、Kryo接口、FST接口等。

       序列化方式如Kryo和FST,性能往往优于hessian2,能够显著提高序列化性能。这些高效Java序列化方式的引入,可以优化Dubbo的序列化过程。

       在配置Dubbo RPC时,引入Kryo和FST非常简单,只需在RPC的XML配置中添加相应的属性即可。

       关于服务消费方发送请求,Dubbo框架定义了私有的RPC协议,消息头和消息体分别用于存储元信息和具体调用消息。消息头包括魔数、数据包类型、消息体长度等。消息体包含调用消息,如方法名称、参数列表等。请求编码和解码过程涉及编解码器的使用,编码过程包括消息头的写入、序列化数据的存储以及长度的写入。解码过程则涉及消息头的读取、序列化数据的解析以及调用方法名、参数等信息的提取。

       提供方接收请求后,服务调用过程包含请求解码、调用服务以及返回结果。解码过程在NettyHandler中完成,通过ChannelEventRunnable和DecodeHandler进一步处理请求。服务调用完成后,通过Invoker的invoke方法调用服务逻辑。响应数据的编码与请求数据编码过程类似,涉及数据包的构造与发送。

       服务消费方接收调用结果后,首先进行响应数据解码,获得Response对象,并传递给下一个处理器NettyHandler。处理后,响应数据被派发到线程池中,此过程与服务提供方接收请求的过程类似。

       在异步通信场景中,Dubbo在通信层面为异步操作,通信线程不会等待结果返回。默认情况下,RPC调用被视为同步操作。Dubbo通过CompletableFuture实现了异步转同步操作,通过设置异步返回结果并使用CompletableFuture的get()方法等待完成。

       对于异步多线程数据一致性问题,Dubbo使用编号将响应对象与Future对象关联,确保每个响应对象被正确传递到相应的Future对象。通过在创建Future时传入Request对象,可以获取调用编号并建立映射关系。线程池中的线程根据Response对象中的调用编号找到对应的Future对象,将响应结果设置到Future对象中,供用户线程获取。

       为了检测Client端与Server端的连通性,Dubbo采用双向心跳机制。HeaderExchangeClient初始化时,开启两个定时任务:发送心跳请求和处理重连与断连。心跳检测定时任务HeartbeatTimerTask确保连接空闲时向对端发送心跳包,而ReconnectTimerTask则负责检测连接状态,当判定为超时后,客户端选择重连,服务端采取断开连接的措施。