这不是一个讲概念的专栏,而且我也不擅长讲概念,每一篇文章都是一个故事,我希望你可以通过这些故事了解我当时在实际工作中遇到问题和背后的思考,架构设计是种经验,我有幸参与到多个亿级系统的架构设计中,有所收获的同时也希望把这些收获分享与大家。

承接上篇,网关是负责接口调用获取请求数据的,HTTP 属于单向操作,建客户端与服务平台的 TCP 双向通道,保持客户端与服务平台的会话状态,则可以提供更多、更灵活的技术实现和业务实现。在业务服务调用上通过 HTTP 网关,在平台服务调用上则通过 TCP 网关,实现平台与业务解耦,并且平台采用 TCP 通道还可以增加对平台的控制力,如下图所示:

本文继续讲述构建 TCP 长连接网关的故事。

1。Session 管理

网关为什么需要 Session 管理?因为 HTTP 网关是单向通信的短连接,是无状态的;而 TCP 网关是双向通信的长连接,是有状态的。所谓有状态,简单的理解,用户在 Web 网站登录会后浏览器会基于 Session 缓存用户的认证信息,以实现用户有状态下的服务访问。HTTP 网关 API 的安全访问目前是基于 OAuth2 技术,而 TCP 网关则可以通过长连接实现访问鉴权后基于 Session 管理实现 API 有状态下的服务访问。而且 TCP 属于 OSI 的传输层,所以建立 Session 管理机制构建会话层来提供应用层服务,可以极大的降低系统复杂度。

TCP 网关的 Session 是客户端与服务端建立的一次会话链接,会话信息中保存着 SessionId、连接创建时间、上次访问事件,以及 Connection 和 SessionListener 对象。因为 TCP 网关采用 Netty 框架,所以 Session 中的 Connection 保存了 Netty 的 ChannelHandlerContext 上下文信息。所有连接的 Session 会话信息会保存在 SessionManager 内存管理器中。

TCP 网关通过在 Netty 的 ChannelPipe 中加载自定义 ChannelHandler,构建 Container 容器,将每个 TCP Connection 封装到一个 Session 会话中,保存在 Container 容器中,由 Container 容器构建 Session Layer 提供 Logic 请求调用,如下图所示:

每一次 Session 的会话请求(ChannelRead)都是通过 Proxy 代理机制调用 Service 层,数据请求完毕后通过写入 ChannelHandlerConext 再传送到 Channel 中。同样,数据下行主动推送也是如此,通过 Session Manager 找到 Active 的 Session,轮询写入 Session 中的 ChannelHandlerContext,就可以实现广播或点对点的数据推送逻辑。

数据上行

数据上行特指从客户端发送数据到服务端,数据从 ChannelHander 的 channelRead 方法获取数据。数据包括创建会话、发送心跳、数据请求等。这里注意的是,channelRead 的数据包括客户端主动请求服务端的数据,以及服务端下行通知客户端的返回数据,所以在处理 object 数据时,通过数据标识区分是请求-应答,还是通知-回复。

数据下行

数据下行通过 MQ 广播机制到所有服务器,所有服务器收到消息后,获取当前服务器所持有的所有 Session 会话,进行数据广播下行通知。如果是点对点的数据推送下行,数据也是先广播到所有服务器,每天服务器判断推送的端是否是当前服务器持有的会话,如果判断消息数据中的信息是在当前服务,则进行推送,否则抛弃。

2。心跳

心跳是用来检测保持连接的客户端是否还存活着,客户端每间隔一段时间就会发送一次心跳包上传到服务端,服务端收到心跳之后更新 Session 的最后访问时间。在服务端长连接会话检测通过轮询 Session 集合判断最后访问时间是否过期,如果过期则关闭 Session 和 Connection,包括将其从内存中删除,同时注销 Channel 等。

上文已提到,TCP 网关长连接容器的 Handler 就是放在 Pipeline 的中,所以,每一个 Channel 对应一个 Connection,一个 Connection 就对应一个 Session,Session 由 Session Manager 管理,Session 与 Connection 是一一对应,Connection 保存着 ChannelHandlerContext(ChannelHanderContext 可以找到 Channel),Session 通过心跳机制来保持 Channel 的 Active 状态。

当然,除了这种方法之外,还可以通过在服务端基于 Session Manager 发送心跳包检测客户端是否还活着,如果尝试无响应,则关闭 Session 和 Connection。

除此之外,Netty 框架也提供了 IdleStateHandler 方法,IdleStateHandler 会检测 channelRead 和 write 方法多久没有被调用了,如果长时间没有调用,就会调用 userEventTriggered 方法。

3。断线重连

客户端与服务端通过 TCP 长连接进行通信,但在中国复杂的网络环境下,移动客户端可能由于网络抖动、弱网络情况下,遭遇非正常网络闪断,如何处理断开后的断线重连?TCP 长连接断开之后,如果重连?如果处理断开后的连接再重连后,找到上一次连接的会话呢?

这个解决得益于 Netty 的 ChannelHandlerContext,它可以存储一些自定义属性到 Channel 的上下文中。在每次成功建立请求的 Channel 里存入 SessionId,将它作为一个钩子,当网络闪断后,再次请求建立连接的 Channel,可以通过判断是否存在 SessionId 的钩子,进行处理。

客户端每通过 TCP 与服务端进行一次建连,都会在服务容器里创建一个 Session 会话,该会话保存 Connection 的句柄,对应 Netty 的一个 Channel 通道。建连成功后,通过定时的心跳保持 Channel 属于 Active 活跃。但客户端进入弱网络环境下,客户端可能已经掉线,但并未向服务端主动发送关闭 Channel 请求,而服务端仍认为该 Channel 仍存活。直到在由服务端的会话存活检测机制检测到 Channel 已经 InActive,才会由服务端销毁该 Channel。

服务端的会话存活检测是 5 分钟一次,所以存在客户端掉线后,在 5 分钟内又重新建连,而这时服务端的建连逻辑,不是重新创建一个 Session,而是去寻找上一次的 Session,并更新标识存活。具体的实现是在每次建连的 Channel 里存入 SessionId,当网络闪断后,判断 Channel 是否存在 Session,之所以实现是得益于 Netty 的 ChannelHandlerContext,可以存储一个自定义属性到 Channel 的上下文中。

当然,TCP 网关一定是集群,所以,断线重连也是极有可能请求到不同的服务器上,而这种情况按照新 Connection 创建的 Session 处理,只有出现重连到同一服务器时,才需要考虑上述的处理逻辑。

4。总结

言而总之,本篇文章重点讲述了 TCP 网关的心跳、Session 管理、断线重连。下篇文章,我将介绍架构演进重构消息 PUSH 系统。如果你觉得有收获,欢迎你把今天的内容分享给更多的朋友。

5。扩展阅读

故事1:从零构建亿级流量API网关
01 | API网关:统一接入、分层架构、高可用架构
02 | 流量调度:配置中心、泛化调用

故事2:架构演进构建TCP长连接网关
03 | TCP网关:Netty框架、Protobuf格式、业务线程池
04 | TCP长连接:心跳、Session管理、断线重连

故事3:架构演进重构消息PUSH系统
05 | 消息PUSH:消息推送、消息送达率、APNs

故事4:从焦油坑爬出来的交易系统
06 | 交易平台:订单管道、订单状态机、服务编排、任务引擎
07 | 微服务化:服务治理、领域设计

故事5:烦人的焦油开始到处都是
08 | 新老系统:业务整合、数据融合、系统迁移
09 | 高可用架构:隔离部署、系统监控与日志、可灰度、可降级

故事6:稳定性架构与大促保障
10 | 大道至简:系统复杂度、三明治架构
11 | 大促保障:自动化测试、故障演练、性能压测

亿级流量架构演进实战 | 架构演进构建TCP长连接网关 04相关推荐

  1. 亿级流量系统多级缓存架构10 阿里云实战

    亿级流量系统多级缓存架构10 阿里云实战 域名购买解析 域名的价值 域名的价值就像商标一样,体现在你注册一个域名之后,别人就不可以再注册这个域名了,域名的稀缺性就产生了.域名可以买卖,一个域名我注册了 ...

  2. 亿级流量的互联网项目如何快速构建?手把手教你构建思路

    一. 大流量的互联网项目 1.项目背景 索尔老师之前负责的一个项目,业务背景是这样的.城市的基础设施建设是每个城市和地区都会涉及到的,如何在基建工地中实现人性化管理,是当前项目的主要诉求.该项目要实现 ...

  3. 阿里P9架构师讲解从单机至亿级流量大型网站系统架构的演进过程

    阶段一.单机构建网站 网站的初期,我们经常会在单机上跑我们所有的程序和软件.此时我们使用一个容器,如tomcat.jetty.jboos,然后直接使用JSP/servlet技术,或者使用一些开源的框架 ...

  4. 系统架构(1)---单机至亿级流量大型网站系统架构演进

    阶段一.单机构建网站 网站的初期,我们经常会在单机上跑我们所有的程序和软件.此时我们使用一个容器,如tomcat.jetty.jboos,然后直接使用JSP/servlet技术,或者使用一些开源的框架 ...

  5. 阿里P9架构师简述从单机至亿级流量大型网站系统架构的演进过程

    阶段一.单机构建网站 网站的初期,我们经常会在单机上跑我们所有的程序和软件.此时我们使用一个容器,如tomcat.jetty.jboos,然后直接使用JSP/servlet技术,或者使用一些开源的框架 ...

  6. 亿级流量架构演进实战 | 架构演进重构消息PUSH系统 05

    这不是一个讲概念的专栏,而且我也不擅长讲概念,每一篇文章都是一个故事,我希望你可以通过这些故事了解我当时在实际工作中遇到问题和背后的思考,架构设计是种经验,我有幸参与到多个亿级系统的架构设计中,有所收 ...

  7. 亿级流量架构演进实战 | 从零构建亿级流量API网关 01

    这不是一个讲概念的专栏,而且我也不擅长讲概念,每一篇文章都是一个故事,我希望你可以通过这些故事了解我当时在实际工作中遇到问题和背后的思考,架构设计是种经验,我有幸参与到多个亿级系统的架构设计中,有所收 ...

  8. 亿级流量架构演进实战 | 从零构建亿级流量API网关 02

    这不是一个讲概念的专栏,而且我也不擅长讲概念,每一篇文章都是一个故事,我希望你可以通过这些故事了解我当时在实际工作中遇到问题和背后的思考,架构设计是种经验,我有幸参与到多个亿级系统的架构设计中,有所收 ...

  9. 亿级流量系统架构演进之路

    海量用户同时进行高频访问对任何平台都是难题,也是行业乐此不疲的研究方向.但值得庆幸的是,虽然业务场景不同,设计和优化的思想却是万变不离宗.本文将结合业务与高并发系统设计的核心技术点,对系统架构调优方案 ...

最新文章

  1. win7操作系统在哪显示隐藏文件夹
  2. IT民工系列——c#操作Microsoft IE,实现自动登录吧!
  3. leetcode最大矩形_LeetCode——最大矩形
  4. 曼彻斯特编码_两种编码方式以及两种帧结构
  5. linux ubuntu文件系统,Ubuntu Linux 文件系统的主要目录
  6. 【转】ubuntu 12.04 /sbin/ldconfig.real: /usr/local/lib/*.so.8 不是符号连接 解决办法
  7. mac应用 已损坏,打不开.你应该将它移到废纸篓
  8. Java复习---基础复习
  9. Editext编辑属性
  10. webpack学习小项目
  11. V2X-ViT:基于Vision Transformer的V2X协同感知
  12. 利用qq邮箱作为个人邮件服务器发送邮件
  13. MyOwnFreeHost免费分销空间定制模板管理用户WHMCS整合和空间运营
  14. 安全运营中心(SOC)从这里开始(一)
  15. centos8 挂载ntfs_CentOS系统挂载U盘、NTFS移动硬盘
  16. keil 添加ARM芯片包 (stm32为例)
  17. SQL Server之STUFF 使用
  18. 如何在 DAX 计算中隐藏未来日期?
  19. MySQL之脏写、脏读、不可重复读、幻读
  20. 制作dvd iso镜像ubuntu

热门文章

  1. 当你完全认清程序员这个行业,你才有走下去的勇气
  2. Space Elevator 太空电梯(洛谷)
  3. 软件设计模块之间7种耦合关系
  4. 计算机设备驱动的作用,浅谈电脑驱动程序的工作原理 详解电脑驱动程序意义...
  5. Java类的加载过程
  6. 【bzoj3555】[Ctsc2014]企鹅QQ
  7. linux php oracle 乱码,oracle linux乱码怎么办
  8. pdb 在同版本下 unplug plug 操作
  9. MySQL更新数据update
  10. mysql aggregate_MySQL-滥用聚合函数(MySQL- Misuse of aggregate function)