标签:
每一个服务器系统的新连接从建立开始时,均会经历多个阶段。比如连接的建立,登录的验证,退出前的资源释放等。同时在具体的消息处理中,还会遇到不可识别的消息事件,或者消息处理时出现数据错误等。这些场景在每个连接的整个生命过程都可能会经历,而系统用户也会期望在某些场景中完成特定的操作。比如统计每一个新建连接的信息,对不同类型的客户进行验证过程等。
在一般的服务器系统中,用户需要主动为每个连接对象维护当前状态,然后在具体业务场景中加入对当前连接状态的判断,并在每一个改变连接状态的场景中执行相关生命周期的操作。这种自身维护连接生命状态的做法,可能会由于未与业务逻辑分离而导致实际业务处理部分代码的混乱,这也增加了用户开发的复杂度,使实际开发工作出错率大大增加。
而对于每一个不同的消息处理过程中,都有可能在业务逻辑中出现处理出错或不可识别的的数据的情景。这些都需要在每个消息处理的代码中添加大量与实际业务无关的错误处理代码。这同样不利于业务代码的编写,加大了开发者重复的工作量。
综合以上问题,在服务器系统的设计中我们提出了设备生命周期的概念,并通过系统对连接状态和处理错误的管理,提取出了连接的生命周期和错误处理相关的接口。当用户需要对某个状态的连接客户进行相关操作时,只需重写相关状态的接口函数,同时对于所有错误操作,即可在具体业务逻辑中处理,也可通过在对应接口函数中实现统一的错误处理过程。这大大简化和便利了服务器用户的开发过程。
同时联系到之前系统对多设备类型的支持,在具体设计中,需要使用的连接生命周期接口在对应的设备类型对象中实现。不同的设备类型中,对于某个生命周期的接口实现不一定相同。同时子类设备类型会继承父类设备类型中实现的接口,同时在子类中还可以对父类实现的接口进行重写。因此我们可以给不同的设备类型制定不同的生命周期接口。
图4-8 连接生命周期
如图4-8所示显示了一个连接从连接建立到断开的生命周期图,包括临时设备类型的生命周期及登录设备的生命周期。其中标示出了在不同场景中系统提供的相关接口。同时服务器系统保证对于每个连接的生命周期接口的回调都将在分配给该连接对象的单一I/O线程中处理,因此对于单个连接而言无需考虑多线程的问题。
以下将对这些接口进行具体介绍:
在不同设备连接的生命周期中,服务器系统为所有管理的设备制定了一套统一的登录机制。整个登录流程如图4-9所示。这个机制既保证了对不同设备的统一管理,同时又提供了三个登录相关的接口供具体设备实现,保证不同设备间登录过程中的差异化处理。
图4-9 登录流程分析
当某个连接用户向服务器请求登录操作时,系统首先检查该连接是否已经登录,如果该连接已经处于登录状态,则直接进入登录成功操作。如果该连接并未登录,系统将根据请求登录消息中传入的类型来为该连接设置设备类型。如果消息中设置的设备类型并不存在,或者并未设置设备类型,系统将默认为该连接设置为登录设备类型(NodeType)。
然后进行登录账号检查操作。此时将进入该连接的具体设备类型的onLoginCheckMsg()回调中。该接口默认实现是不进行任何检查操作,直接返回为True。我们可以根据不同设备对于登录账号检查的要求的不同,在不同设备类型对象中重写该接口实现。比如根据请求登录消息中传来的账号及密码信息,查询数据库进行校验等。同时也可以在此根据账号密码信息给该连接分配一个登录ID,如果未分配,将采用系统分配的临时ID作为登录ID。如果账号检查失败,则该次登录操作失败,直接返回False,并退出整个登录操作。如果账号检查成功,返回True,但这并不意味着该连接已经登录成功,因为该连接并未真正执行登录操作。
账号检查成功后,将进入真正的登录操作中,系统将尝试将该连接信息注册到对应设备类型的连接池中,并将该连接从临时设备类型的连接池中删除。但此时依旧可能出现该账号对应ID已经在其他客户端登录或正在登录的错误,导致系统无法完成该连接的登录操作。如果这种情况产生,将回调onLoginFailureMsg()接口。我们可以通过该接口来通知该连接客户此次登录失败及可能的原因。当执行完该接口后将退出整个登录操作。
如果系统执行登录操作成功后,将会回调执行onLoginSuccessMsg()接口。当该接口被执行时,该次登录操作才算真正的登录成功。因此我们可以通过该接口来通知连接客户此次登录成功的消息。该接口执行完成后,此次登录操作结束。
不同于登录过程只存在单一的入口,即通过登录消息事件进行。连接的退出操作存在多种可能。比如对于已经登录的连接用户,最正常的方式是通过logout注销消息事件进行主动退出。但是同样存在其他多种可能:比如远程客户并未发送任何消息突然断开了服务器连接的情景,或者连接客户长期没有发送任何消息导致服务器检测到该连接超时等。我们需要对这些退出操作制定统一的管理,防止异常的退出使服务器系统无法及时释放相关资源,影响系统性能。
图4-10 退出流程分析
如图4-10所示,如果为连接客户通过logout注销事件请求退出,系统将执行在登录设备类型中注册的该事件的注销处理函数。在注销处理函数中,将会调用该连接实际设备类型的onLogoutMsg接口,通过该接口可以通知连接客户该连接即将被系统关闭。然后将会调用该连接类型的releaseConnNode接口,释放该连接用户申请的相关资源。最后系统将会对该连接执行实际退出操作,强制将该连接从连接池中移除,并且对连接进行关闭。
如果连接客户并未请求注销事件,而是直接断开了与服务器的连接。此时服务器系统将通过该连接套接字的read系统调用返回为0检测到该连接已经异常退出。由于此时连接已经断开,因此并无再次通知连接客户的必要,因此系统将直接调用该连接类型的releaseConnNode接口,释放该连接用户申请的相关资源。并执行实际退出操作,强制将该连接从连接池中移除,并且对连接进行关闭。
如果是服务器通过超时机制检测到某个连接超时,系统将对该连接执行超时处理。在超时处理中,系统将通过线程任务队列保证在该连接的线程中执行连接超时处理函数,此时将会调用该连接类型的onOverTime接口,留给用户处理连接超时的场景。然后同样releaseConnNode接口,释放该连接用户申请的相关资源。并执行实际退出操作,强制将该连接从连接池中移除,并且对连接进行关闭。
以上三种情形中均会调用releaseConnNode接口,因此在该接口的实现中我们应该保证兼容这些情景,只进行连连接用户申请的相关资源的释放工作。其他具体场景相关的处理工作再在其他相关接口中实现。
标签:
原文地址:http://www.cnblogs.com/moyangvip/p/5586038.html