[TOC]node
即时通信IM技术领域基础篇mysql
我经历的xxx项目中的状况:linux
Access接入层服务, tcp长链接的, 若是须要更新的话, 那不是客户端须要从新登陆 ?ios
access 分为链接层和 access,前者不涉及业务,因此预期不用重启,后者承载业务,更新重启对链接没有影响。后面还考虑把 push 合进 accessnginx
链接层和 access 经过共享内存来维护链接信息。golang
调整接入层有状态=>无状态, 接入层与逻辑层严格分离.redis
无状态的接入层,能够随时重启算法
逻辑服务层,能够经过etcd来作服务发现和注册,方便升级和扩容sql
操做系统包含最大打开文件数(Max Open Files)限制, 分为系统全局的, 和进程级的限制数据库
每一个tcp的socket链接都要占用必定内存
网络限制
一些基本经常使用的sysctl的修改:
n = (mempages * (PAGE_SIZE / 1024)) / 10;
PAGE_SIZE:typically 4096 in an x86_64
files_stat.max_files = n;
epoll机制,长链接数太多,会影响性能吗? <底层采用红黑树和链表来管理数据>
实际应用中应该考虑哪些点呢?
网卡多队列的支持, 查看网卡是否支持,要否则cpu不能很好处理网络数据, 这个须要好的网卡,也消耗cpu
维护tcp长链接的节点管理, 这个须要消耗cpu, 须要有对应的数据结构来进行管理
实际中,还应该考虑,每秒中可以创建链接的速度,由于百万链接并非一下就创建的,若是重启了重连,那么链接速度如何呢 ?
若是这个节点挂掉了,请求的分摊处理怎么弄?
应用层对于每一个链接的处理能力怎样? 服务端对协议包的解析处理能力如何 ?
tcp mem 问题,没有用到就不会分配内存, 可是不必定会立刻回收.
关于长链接的另外考虑点:
在稳定链接状况下,长链接数这个指标,在没有网络吞吐状况下对比,其实意义每每不大,维持链接消耗cpu资源很小,每条链接tcp协议栈会占约4k的内存开销,系统参数调整后,咱们单机测试数据,最高也是能够达到单实例300w长链接。但作更高的测试,我我的感受意义不大。
实际网络环境下,单实例300w长链接,从理论上算压力就很大:实际弱网络环境下,移动客户端的断线率很高,假设每秒有1000分之一的用户断线重连。300w长链接,每秒新建链接达到3w,这同时连入的3w用户,要进行注册,加载离线存储等对内rpc调用,另外300w长链接的用户心跳须要维持,假设心跳300s一次,心跳包每秒须要1w tps。单播和多播数据的转发,广播数据的转发,自己也要响应内部的rpc调用,300w长链接状况下,gc带来的压力,内部接口的响应延迟可否稳定保障。这些集中在一个实例中,可用性是一个挑战。因此线上单实例不会hold很高的长链接,实际状况也要根据接入客户端网络情况来决定。
注意的一点就是close_wait 过多问题,因为网络不稳定常常会致使客户端断连,若是服务端没有可以及时关闭socket,就会致使处于close_wait状态的链路过多。
考虑到不一样地区不一样网络运营商的状况下,用户可能由于网络限制,链接不上咱们的服务或者比较慢。
TCP_NODELAY
针对这个话题,Thompson认为不少在考虑微服务架构的人对TCP并无充分的理解。在特定的场景中,有可能会遇到延迟的ACK,它会限制链路上所发送的数据包,每秒钟只会有2-5个数据包。这是由于TCP两个算法所引发的死锁:Nagle以及TCP Delayed Acknowledgement。在200-500ms的超时以后,会打破这个死锁,可是微服务之间的通讯却会分别受到影响。推荐的方案是使用TCP_NODELAY,它会禁用Nagle的算法,多个更小的包能够依次发送。按照Thompson的说法,其中的差异在5到500 req/sec。
tcp_nodelay 告诉nginx不要缓存数据,而是一段一段的发送--当须要及时发送数据时,就应该给应用设置这个属性,这样发送一小块数据信息时就不能当即获得返回值。
咱们发现 gRPC 的同步调用与 Nagle's algorithm 会产生冲突,虽然 gRPC 在代码中加入了 TCP_NODELAY 这个 socketopt 但在 OS X 中是没有效果的。后来经过设定 net.inet.tcp.delayed_ack = 0 来解决,一样咱们在 linux 下也设置了 net.ipv4.tcp_low_latency = 1,这样在 100M 带宽下一次同步调用的时间在 500us 如下。并且在实际应用中,咱们经过 streaming 调用来解决大量重复数据传输的问题,而不是经过反复的同步调用来传相同的数据,这样一次写入能够在 5us 左右。其实批量写入一直都是一个很好的解决性能问题的方法S
心跳其实有两个做用
最多见的就是每隔固定时间(如4分半)发送心跳,可是这样不够智能.
心跳算法 (参考Android微信智能心跳策略)
精简心跳包,保证一个心跳包大小在10字节以内, 根据APP先后台状态调整心跳包间隔 (主要是安卓)
网络加速 cdn
协议精简和压缩
TCP第一次经过域名链接上后,缓存IP,下次进行IP直连;若下次IP链接失败,则从新走域名链接
对于大文件和图片等, 使用断点上传和分段上传
平衡网络延迟和带宽的影响
ip就近接入
掉线后,根据不一样的状态须要选择不一样的重连间隔。若是是本地网络出错,并不须要定时去重连,这时只须要监听网络状态,等到网络恢复后重连便可。若是网络变化很是频繁,特别是 App 处在后台运行时,对于重连也能够加上必定的频率控制,在保证必定消息实时性的同时,避免形成过多的电量消耗。
断线重连的最短间隔时间按单位秒(s)以四、八、16...(最大不超过30)数列执行,以免频繁的断线重连,从而减轻服务器负担。当服务端收到正确的包时,此策略重置
有网络但链接失败的状况下,按单位秒(s)以间隔时间为二、二、四、四、八、八、1六、16...(最大不超过120)的数列不断重试
重连成功后的策略机制
在重连Timer中,为了防止雪崩效应的出现,咱们在检测到socket失效(服务器异常),并非立马进行重连,而是让客户端随机Sleep一段时间(或者上述其余策略)再去链接服务端,这样就可使不一样的客户端在服务端重启的时候不会同时去链接,从而形成雪崩效应。
通常的话,有网络切换(3g->4g->wifi->4g)就重连,从新走一遍总体流程
最好APP能以尽可能少的通信量来从新注册服务器, 好比再也不从服务器获取配置信息,从上一次拉取的服务器配置的缓存数据直接读取(若是服务器改变,最好可以发一条通知给app更新)
如从wifi 切换到4G、处于地铁、WIFI边缘地带等,为避免形成重连风暴(由于网络不稳定,会频繁发起重连请求), 能够采用稍加延迟重连策略
采用业界经常使用的分布式服务发现,配置方案. 如经过etcd来进行服务发现和注册.
设计的各个模块要能独立化部署,设计为无状态,例如所谓的微服务, 这样才可以很好的作服务的升级、扩容, 保证无单点故障, 也方便灰度发布更新
动态配置
消息是写扩散,仍是读扩散: 群里面每一个人都写一次相同的消息,仍是群里面都从同一个地方读取这条相同消息?
写扩散: 简单,可是群里面每一个人都要写一遍缓存.数据量有点大,并且增长网络消耗(好比写redis的时候).
读扩算: 只写一份到缓存,拉取的时候,从这个群缓存消息里面拉,须要增长一点逻辑处理,方便在全部群成员都拉取完后删掉缓存数据(或者过时)
发送方式
遍历群成员,若是在线就依次发送, 可是群成员多,群活跃的时候,可能会增大压力.
遍历群成员, 在线人员, 服务内部流转(rpc)的时候是否能够批量发送?
群方式
对于群消息,每条消息都须要拉取群成员的在线状态.若是存放在redis,拉取会太过频繁.链接数会暴增,并发太高. 这样能够增长一级本地缓存,把链接信息放到本地缓存(经过消耗内存来减小网络链接和请求)
不能影响手机休眠,采用alarm manager触发心跳包
尽可能减小网络请求,最好可以合并(或者一次发送多个请求). 批量、合并数据请求/发送
移动网络下载速度大于上传速度,2G一次发送数据包不要太大,3G/4G一次发送多更省电.
消息头包含字段dup, 若是是重复递送的消息,置位此字段,用来断定重复递送
服务端缓存对应的msgid列表, 客户端下发已收到的最大msgid, 服务端根据客户端收到的最大msgid来判断小于此id的消息已经所有被接收.这样保证消息不丢.
服务端确保msgid生成器的极度高的可用性,而且递增, 经过msgid的大小,来保证消息的顺序
为了达到任意一条消息都不丢的状态,最简单的方案是手机端对收到的每条消息都给服务器进行一次ack确认,但该方案在手机端和服务器之间的交互过多,而且也会遇到在弱网络状况下ack丢失等问题。所以,引入sequence机制
** 方案优势 **
根据服务器和手机端之间sequence的差别,能够很轻松的实现增量下发手机端未收取下去的消息
对于在弱网络环境差的状况,丢包状况发生几率是比较高的,此时常常会出现服务器的回包不能到达手机端的现象。因为手机端只会在确切的收取到消息后才会更新本地的sequence,因此即便服务器的回包丢了,手机端等待超时后从新拿旧的sequence上服务器收取消息,一样是能够正确的收取未下发的消息。
因为手机端存储的sequence是确认收到消息的最大sequence,因此对于手机端每次到服务器来收取消息也能够认为是对上一次收取消息的确认。一个账号在多个手机端轮流登陆的状况下,只要服务器存储手机端已确认的sequence,那就能够简单的实现已确认下发的消息不会重复下发,不一样手机端之间轮流登陆不会收到其余手机端已经收取到的消息。
IM系统的主要需求:包括帐号、关系链、在线状态显示、消息交互(文本、图片、语音)、实时音视频
http模式(short连接)和 tcp 模式(long 连接),分别应对状态协议和数据传输协议
保持长链接的时候,用TCP. 由于须要随时接受信息. 要维持长链接就只能选TCP,而非UDP
获取其余非及时性的资源的时候,采用http短链接. 为啥不所有用TCP协议呢? 用http协议有什么好处?
IM到底该用UDP仍是TCP协议
UDP和TCP各有各的应用场景,做为IM来讲,早期的IM由于服务端资源(服务器硬件、网络带宽等)比较昂贵且没有更好的办法来分担性能负载,因此不少时候会考虑使用UDP,这其中主要是早期的QQ为表明。
TCP的服务端负载已经有了很好的解决方案,加之服务器资源成本的降低,目前不少IM、消息推送解决方案也都在使用TCP做为传输层协议。不过,UDP也并未排除在IM、消息推送的解决方案以外,好比:弱网络通讯(包括跨国的高延迟网络环境)、物联网通讯、IM中的实时音视频通讯等等场景下,UDP依然是首选项。
关于IM到底该选择UDP仍是TCP,这是个仁者见仁智者见智的问题,没有必要过于纠结,请从您的IM总体应用场景、开发代价、部署和运营成本等方面综合考虑,相信能找到你要的答案。
经常使用IM协议:IM协议选择原则通常是:易于拓展,方便覆盖各类业务逻辑,同时又比较节约流量。后一点的需求在移动端IM上尤为重要?
xmpp: 协议开源,可拓展性强,在各个端(包括服务器)有各类语言的实现,开发者接入方便。可是缺点也是很多:XML表现力弱,有太多冗余信息,流量大,实际使用时有大量天坑。
MQTT: 协议简单,流量少,可是它并非一个专门为IM设计的协议,多使用于推送. 须要本身在业务上实现群,好友相关等等. 适合推送业务,适合直播IM场景。
SIP: 多用于VOIP相关的模块,是一种文本协议. sip信令控制比较复杂
私有协议: 本身实现协议.大部分主流IM APP都是是使用私有协议,一个被良好设计的私有协议通常有以下优势:高效,节约流量(通常使用二进制协议),安全性高,难以破解。
协议设计的考量:
网络数据大小——占用带宽,传输效率:虽然对单个用户来讲,数据量传输很小,可是对于服务器端要承受众多的高并发数据传输,必需要考虑到数据占用带宽,尽可能不要有冗余数据,这样才可以少占用带宽,少占用资源,少网络IO,提升传输效率;
网络数据安全性——敏感数据的网络安全:对于相关业务的部分数据传输都是敏感数据,因此必须考虑对部分传输数据进行加密
编码复杂度——序列化和反序列化复杂度,效率,数据结构的可扩展性
协议通用性——大众规范:数据类型必须是跨平台,数据格式是通用的
经常使用序列化协议比较
提供序列化和反序列化库的开源协议: pb,Thrift. 扩展至关方便,序列化和反序列化方便
文本化协议: xml,json. 序列化,反序列化容易,可是占用体积大.
定义协议考量
包数据能够考虑压缩,减少数据包大小
包数据考虑加密,保证数据安全
协议里面有些字段uint64,能够适当调整为uint32.减少包头大小
协议头里面最好包含seq_num
编码角度:采用高效的网络模型,线程模型,I/O处理模型,合理的数据库设计和操做语句的优化;
垂直扩展:经过提升单服务器的硬件资源或者网络资源来提升性能;
水平扩展:经过合理的架构设计和运维方面的负载均衡策略将负载分担,有效提升性能;后期甚至能够考虑加入数据缓存层,突破IO瓶颈;
系统的高可用性:防止单点故障;
在架构设计时作到业务处理和数据的分离,从而依赖分布式的部署使得在单点故障时能保证系统可用。
对于关键独立节点能够采用双机热备技术进行切
数据库数据的安全性能够经过磁盘阵列的冗余配置和主备数据库来解决。
TCP的拥塞控制由4个核心算法组成:“慢启动”(Slow Start)、“拥塞避免”(Congestion voidance)、“快速重传 ”(Fast Retransmit)、“快速恢复”(Fast Recovery)。
kafka队列,没有满的概念, 只有消费滞后/堆积的概念
经过offset monitor 监控对kafka进行实时监控
对于kafka
自己就是一个分布式,自己就能给支持这种线性的扩展,因此不会面临这种问题。
你会写数据不消费么。
写: 先写数据库,成功后,更新缓存
读: 先读缓存, 没有数据则穿透到db.
可是, 假如我写数据库成功,更新缓存失败了. 那下次读的时候,就会读到脏数据(数据不一致),这种状况怎么处理?
方案:
先淘汰缓存,再写数据库. 可是若是在并发的时候,也可能出现不一致的问题,就是假如淘汰掉缓存后,尚未及时写入db, 这个时候来了读请求,就会直接从db里面读取旧数据.
因为数据库层面的读写并发,引起的数据库与缓存数据不一致的问题(本质是后发生的读请求先返回了),可能经过两个小的改动解决:
修改服务Service链接池,id取模选取服务链接,可以保证同一个数据的读写都落在同一个后端服务上
修改数据库DB链接池,id取模选取DB链接,可以保证同一个数据的读写在数据库层面是串行的
数据库为何要分库分表? 什么状况下分库分表 ?
解决磁盘系统最大文件限制
减小增量数据写入时的锁 对查询的影响,减小长时间查询形成的表锁,影响写入操做等锁竞争的状况. (表锁和行锁) . 避免单张表间产生的锁竞争,节省排队的时间开支,增长呑吐量
因为单表数量降低,常见的查询操做因为减小了须要扫描的记录,使得单表单次查询所需的检索行数变少,减小了磁盘IO,时延变短
一台服务器的资源(CPU、磁盘、内存、IO等)是有限的,最终数据库所能承载的数据量、数据处理能力都将遭遇瓶颈。分库的目的是下降单台服务器负载,切分原则是根据业务紧密程度拆分,缺点是跨数据库没法联表查询
当数据量超大的时候,B-Tree索引的做用就没那么明显了。若是数据量巨大,将产生大量随机I/O,同时数据库的响应时间将大到不可接受的程度。
goroutine都是用户态的调度, 协程切换只是简单地改变执行函数栈,不涉及内核态与用户态转化, 上下文切换的开销比较小.
建立一个goroutine须要大概2k(V1.4)左右的栈空间.
go有抢占式调度:若是一个Goroutine一直占用CPU,长时间没有被调度过,就会被runtime抢占掉
是否是表示,在内存够用的条件下, 建立必定量(好比,30w,50w)的goroutine, 不会由于cpu调度缘由致使性能降低太多?
若是系统里面goroutine太多, 可能缘由之一就是由于每一个goroutine处理时间过长,那么就须要查看为啥处理耗时较长.
给出大概数据,24核,64G的服务器上,在QoS为message at least,纯粹推,消息体256B~1kB状况下,单个实例100w实际用户(200w+)协程,峰值能够达到2~5w的QPS...内存能够稳定在25G左右,gc时间在200~800ms左右(还有优化空间)。 (来自360消息系统分享)
长链接接入层的net链接不少,通常单台服务器能够有几十万、甚至上百万,那么怎么管理这些链接 ? 后端数据来了, 怎么快速找到这个请求对应的链接呢 ? 链接和用户如何对应
一个链接结构. 包含tcp链接信息,上次通讯时间, 加解密sharekey, clientaddr. 还包含一个用户结构
用户结构里面包含uid, deviceid. name ,version ...., 还包含上面的这个链接, 二者一一对应.
不用map来管理, 而是把tcp链接信息和user信息来进行一一对应,若是map的话,几百万可能查找起来比较慢.
登陆请求的时候,能够根据这个tcp链接信息,获取user信息,可是此时user信息基本没有填充什么数据,因此就须要根据登陆来填充user信息结构. 关键是: 在当前Access接入服务里面,会有一个useMap,会把uid和user信息对应起来,能够用来判断此uid,是否在本实例上登陆过
返回数据的时候, 能够根据这个uid,来获取对应的user结构,而后经过这个结构能够获取对应的tcp 链接信息, 能够进行发送信息.
另外,登陆登出的时候,会有另外的链接信息(uid/topic/protoType/addr...) 添加删除到用户中心
若是有多个Access接入层, 每一个接入层都会有一个useMap结构.
数据结构: map/hash(红黑树)
利用map数据结构, 发送(publish)完消息后,当即经过msgid和uid,把对应的消息体添加到map结构.
收到回应后,删除对应的map结构.
超时后,从新提交OfflineDeliver. 而后删除对应的map结构.
client线程每次经过socket调用一次远程接口前,生成一个惟一的ID,即requestID(requestID必需保证在一个Socket链接里面是惟一的),通常经常使用AtomicLong从0开始累计数字生成惟一ID,或者利用时间戳来生成惟一ID.
grpc 也须要服务发现. grpc服务可能有一个实例. 2个, 甚至多个? 可能某个服务会挂掉/宕机. 能够利用zookeeper来管理.
同步 RPC 调用一直会阻塞直到从服务端得到一个应答,这与 RPC 但愿的抽象最为接近。另外一方面网络内部是异步的,而且在许多场景下可以在不阻塞当前线程的状况下启动 RPC 是很是有用的。 在多数语言里,gRPC 编程接口同时支持同步和异步的特色。
gRPC 容许客户端在调用一个远程方法前指定一个最后期限值。这个值指定了在客户端能够等待服务端多长时间来应答,超过这个时间值 RPC 将结束并返回DEADLINE_EXCEEDED错误。在服务端能够查询这个期限值来看是否一个特定的方法已通过期,或者还剩多长时间来完成这个方法。 各语言来指定一个截止时间的方式是不一样的
编码角度:
垂直扩展:
水平扩展:
系统的高可用性:
在架构设计时作到业务处理和数据的分离,从而依赖分布式的部署使得在单点故障时能保证系统可用。
对于关键独立节点能够采用双机热备技术进行切换。
数据库数据的安全性能够经过磁盘阵列的冗余配置和主备数据库来解决。
经过压测得知gRPC是瓶颈影响因素之一,为啥是grpc? 为啥消耗cpu? 怎么解决? 网络必定不会影响吞吐.
采用uarmy 方式. 能够考虑采用streaming方式. 批量发送,提升效率
uarmy方式一对一,并发增大的时候,链接数会增大
streaming方式的话,就是合并多个请求(批量打包请求/响应), 减小网络交互, 减小链接
作过streaming 的压测,性能说比 unary 高一倍还多
通常服务器都会有个抛物线规律, 随着并发数的增大,会逐渐消耗并跑满(cpu/内存/网络带宽/磁盘io), 随之带来的就是响应时间变慢(时延Latency变成长),而qps/吞吐量也上不去.
对于grpc 而言, 并发数增多后,能看到实际效果就是延迟增大,有部分请求的一次请求响应时间达到了5s左右(ACCESS/PUSH), 这样说明时延太长, qps/吞吐量 = 并发数/响应时间. 响应时间太长,吞吐固然上不去.
为啥响应时间这么长了? 是由于cpu跑满了么?
还有一个缘由却是响应慢,那就是最终请求会到Oracle服务, 而oracle会请求数据资源(cache/db), oracle的设计中请求资源的并发增多(链接数也增多),致使请求资源的时延增加,所以返回到上级grpc的调用也会增大时延.
所以关键最终又回到了 cpu/内存/网络带宽/磁盘io这里了
rpc 而言, 链接数增多了,会致使:
相似tcp长链接同样, 每一个链接确定要分配必定的内存
要同时处理这么多链接,每一个链接都有相应的事务, cpu的处理能力要强
后来通过调查咱们发现 gRPC 的同步调用与 Nagle's algorithm 会产生冲突,虽然 gRPC 在代码中加入了 TCP_NODELAY 这个 socketopt 但在 OS X 中是没有效果的。后来经过设定 net.inet.tcp.delayed_ack = 0 来解决,一样咱们在 linux 下也设置了 net.ipv4.tcp_low_latency = 1,这样在 100M 带宽下一次同步调用的时间在 500us 如下。并且在实际应用中,咱们经过 streaming 调用来解决大量重复数据传输的问题,而不是经过反复的同步调用来传相同的数据,这样一次写入能够在 5us 左右。其实批量写入一直都是一个很好的解决性能问题的方法
若是服务器在北京, 客户端在广州, 如何可以快速接入? 除了走cdn还有其余方式没 ?
若是只有一个数据中心, 暂时除了cdn加速, 没有其余方法.
若是有两个数据中心, 能够采起就近原则,可是须要两个数据中心的数据进行同步
就近接入:就是利用DNS服务找到离用户最近的机器,从而达到最短路径提供服务
要能在不压测的状况下,就可以预估出系统可以支持的qps. 要可以粗略估算出一次db的请求耗时多久, 一次redis的请求耗时多少, 一次rpc调用的请求耗时多少?
全部系统, 必定都是分为几层, 从上层到底层, 每一步的请求是如何的? 在每一个层耗时咋样?
系统有没有引入其余资源
性能瓶颈没法是cpu/io.
db查询慢,是为啥慢? 慢必定有缘由的?
单台机, qps为8k, 是比较少的. qps: 8k, 那么平均请求响应时间: 1/8ms=0.125ms, qps为8k, 那么5台机器, qps就是4w, 同时10w人在线, 收发算一个qps的话,那么qps减半, 那就是2w qps, 10w同时在线, 每一个人3-4s发一次消息, 须要qps到3w.
以前测试redis的时候, 有测试过,若是并发过高,会致使拉取redis耗时较长,超过3s左右.
正常状况下,一我的发送一条消息须要耗时至少5s左右(6-8个字).
要深刻提升IM技术, 就必需要可以学会分析性能, 找到性能瓶颈, 并解决掉.
架构都是逐步改造的, 每一个阶段有每一个阶段的架构, 通常架构,初始都是三层/四层架构. 而后开始改造, 改造第一阶段都是拆分服务,按逻辑拆分,按业务拆分, 合并资源请求,减小并发数,减小链接数.
要常常关注一些大数据, 好比注册用户数, 日活, 月活, 留存. 要对数据敏感, 为何一直不变, 为何忽然增高, 峰值是多少? 目前能抗住多少 ?
关注系统性能指标,cpu,内存,网络,磁盘等数据, 常常观测, 看看有没有异常, 作到提早发现问题,而不是等到问题出现了再进行解决, 就是是出现问题了再进行解决, 也要保证解决时间是分钟级别的.
彻底理解系统底层工具的含义,如sar,iosta,dstat,vmstat,top等,这些数据要常常观察,常常看
保证整套系统中所涉及的各个部分都是白盒的
依赖的其余服务是谁负责,部署状况,在哪一个机房
使用的资源状况,redis内存多大 ? mysql 数据库多少? 表多少? 主从怎么分布 ? 对于消息: 一主两从,32库,32表. 对于好友数据:一主一从,128表. 对于朋友圈,按月分表.
若是没有本身思考,现有的东西都是合理的, 这显然是不行的.
每看一个东西,都要思考, 这个东西合不合理? 是否能够优化? 有哪些相似的? 要想若是怎么样
例如:刚开始接触xxx项目的时候,以为这个架构不错,以为不用优化了,可是后面须要大规模推广后,xxx就提出了一些优化点, 经过量级的提升,暴露了一些问题
并发大后,mysql慢请求问题
并发大后,请求资源并发太多,链接数太多问题,所以须要合并资源请求
Access接入层长链接的问题, Access接入层服务升级不方便, 所以须要拆分Access长链接,提高稳定性.方便服务升级.
除了熟悉代码框架外, 必定还要深刻到细节, 好比golang的底层优化, 系统级别的优化.
围绕im领域思考问题和量级, 当前的量级是什么级别,而后须要考虑更高级别要作的事情.
了解业界相关技术方案, 了解别人踩过的坑. 用来后续量大了后,能够提供更好的技术方法和架构, 往资深im/im高级方向发展, 不只仅限于xxx项目. 要可以围绕整个IM 领域方向思考
【"欢迎关注个人微信公众号:Linux 服务端系统研发,后面会大力经过微信公众号发送优质文章"】