《亿级流量JAVA高并发与网络编程实战》笔记

第一章 高并发概述

  1. 高并发技术

是一个广义的概念,是指一种高效的地实现并发需求的解决方案,是技术领域的名称,可以包含架构设计、SOA(面向服务的架构)、分布式、微服务、数据处理、多线程等众多的细分知识。

第二章 系统分析与大型互联网架构设计

2.1系统分析原则

概述:在开发大型系统是,除了根据业务需求实现相应的功能模块外,还需要从高性能和高可用等多个维度对系统进行设计。

2.1.1.高并发原则

垂直扩展:通过软件技术或升级硬件来提高单机的性能。就好比当一头小牛无法拉动货物时,就把小牛换成体能强壮的大牛。

水平扩展:通过增加服务器的节点个数来横向扩展系统的性能。就好比当一头牛无法拉动货物,就可以把货物拆分,然后用多头牛去拉,即分布式。或者用多头牛一起拉这批这一批货物,即集群。

衡量高并发的常见指标包括相应时间、吞吐量或QPS(Query per Second,每秒查询率)、并发用户数等。

2.1.2.容错原则

如果高并发使用不当时,就容易造成各种逻辑混乱的情景,因此需要对各种潜在的问题做好预案,确保系统拥有一定的容错率。

此外,在分布式系统中网络延迟等问题是不可避免的。一般来讲,可以在长连接的环境下通过“心跳检测机制”来处理。(客户端每隔60s向服务端发送一次心跳,如果连续N次都没有收到某个客户端的心跳,就可以认定客户端已经离线)。

为了进一步提高容错性,还可以预先采用“隔离”的手段。对于秒杀等可预知的流量暴增情况,就可以提前将秒杀隔离成独立的服务,防止秒杀服务影响系统中的其他服务。当然,如果预计流量增加的不是特别多,也可以使用多级缓存来解决高并发问题。

2.1.3. CAP原则

一致性、可用性、分区容错性(三者不可兼得,最多只能满足两个)。
一致性:在同一时刻,所有节点中的数据都是相同的。
可用性:在合理的时间范围内,系统能够提供正常的服务。
分区容错性:当分布式系统的一个节点或多个节点发生网络故障,从而脱离整个系统的网络环境时,系统仍然能够提供正常的服务。

2.1.4.幂等性原则

幂等性原则是对调用服务次数的一种限制,即无论对某个服务提供的接口调用多次或是一次,其结果都是相同的。(例:防止用户重复支付等)
对于分布式或微服务系统,为了实现幂等性,可以在写操作之前通过执行读操作来实现。(还可以通过“去重表”、CAS算法、分布式锁、悲观锁等方式实现幂等性。)

2.1.5.可扩展原则

可扩展原则要从项目架构、数据库设计、技术选型和编码规范等多方面考量。(例如:可以使用面向接口、前后端分离及模块化的编程风格,采用无状态化服务,使用高内聚低耦合的编程规范,在设计时预留一些后期扩展时可能会使用到的接口,或者提前设计好项目扩展的解决方案。)

2.1.6.可维护原则和可监控原则
可维护原则 是指系统在开发完毕后,维护人员能够方便地改进或修复系统中存在的问题。可维护性原则包含可理解性、可修改性和可移植性等多方面因素。(1、项目的日志功能完善,易于追溯问题、统计操作情况。2、有Bug管理工具。3、有丰富的项目文档和注释。4、统一开发规范。5、使用模块化的编程模式。)

可监控性原则 是指对流量、性能、服务、异常等情况进行实时监控。还需要对项目关键技术做性能的监控,确保新技术的引入能够带来性能的提升。

2.2系统设计要点

概述:在系统设计时,如果能预先看到一些问题,并在设计层面提前解决,就会给后期的开发带来很大的便捷。相反,有缺陷的架构设计可能会导致后期的开发工作十分的艰难甚至会造成“推倒重来”的情形。因此,在设计阶段,应该尽可能地规避项目开发中可能会遇到的各种问题。

2.2.1Session共享问题

在Web项目中,Session是服务端用于保存客户端信息的重要对象。单系统中的Session对象可以直接保存至内存中,但分布式或集群环境下,多个不同的节点就需要采取措施来共享Session对象。

1、Session Replication

Session Replication是指在客户端第一次发送请求后,处理该请求的服务端就会创建一个对应的Session对象,用于保存用户的状态信息,之后为了让其他服务端也能保存一份此Session对象,据需要将此Session对象在各个服务器端节点之间进行同步。

Session Replication的这种Session同步机制容易引起广播风暴,因此会增大网络开销。其次会造成严重的冗余。因此,Session Replication方式只适合服务节点较少的场景。

java流量统计 java亿级流量_应用服务

2、Session Sticky

Session Sticky是通过Nginx等负载均衡工具对各个用户进行标记(如Cookie标记),是每个用户在经过负载均衡工具后都请求固定的服务节点。因此,各个服务的Session就无需同步。但这种做法也有严重的弊端,如果某个服务节点宕机,那么该节点上的所有Session对象都会丢失。

java流量统计 java亿级流量_java_02

3、独立Session服务器

除了以上两种方式外,还可以将所有Session对象都存放到一个独立的Session服务中,之后各个应用服务再分别从这个Session服务中获取需要的Session对象。在大规模分布式系统中,推荐使用这种独立Session服务方式,这种方式储存Session对象时,既可以用数据库,又可以使用各种分布式或集群存储系统。

java流量统计 java亿级流量_java_03

2.2.2优先考虑无状态服务

在使用了“独立Session服务器”后,应用服务就是一种无状态服务,换句话说,此时的应用服务与用户的状态是无关的。例如,无论哪个用户在什么时间发出的请求,所有的应用服务都会进行相同的处理:先从Session服务中获取Session对象,在进行相同的业务处理。

有状态服务是指不同的应用服务与用户状态有着密切的关系。例如不同应用服务因为用户状态的持有情况不同,从而导致的执行方式的不同就可以理解为“有状态服务”。

无状态服务优势

1、数据同步

“有状态服务”为了在不同的服务节点之间共享数据,必然会进行数据同步,而不同节点之间数据同步又会带来CPU/内存损耗、网络延迟、数据冗余;而“无状态服务”不需要数据同步。

2、快速部署

如果需要增加新的服务节点对系统进行扩容。如果采用“有状态服务”,就需要在扩容后先将其他服务节点上的Session等信息同步到新节点上;而采用“无状态服务”,就不必同步。

这里的状态不仅仅是Session,也可以是任意类型的数据(结构化数据、非结构化数据)、文件等。因此想要真正地实现应用服务的“无状态”就需要将各种类型的“状态”各自集中存储。

java流量统计 java亿级流量_java_04


明确了各种状态的存储方式后,我们就可以搭建出一套快速扩容的系统。将系统中的应用服务设置为无状态,并注册到Eureka或者Zookeeper、Nacos中。因为是无状态的服务,所以单个服务不会影响到集群中的其他服务。另外将有数据的服务设置为有状态,并进行集群的集中部署(如MySQL集群),从而降低集群内部数据同步带来的延迟。

无状态服务虽然有很多优势,但也不要将其作为唯一选择。如小型项目,就可以采用有状态服务来降低开发难度,缩短开发周期。

2.2.3技术选型原则与数据库设计

在做技术选型时,既要注意待选技术的性能,又要考虑技术的安全性,并预估这些技术是否有足够长生命力,项目新成员能否快速掌握,而不能一味的追求技术的先进性。