电商项目怎样处理或用啥技术解决高负载、高并发、高可用性问题( 三 )


\u0026gt;\u0026gt;\u0026gt;\u0026gt;0x0B Reactor多线程模型
在Linux操作系统上,性能最为可靠、稳定的IO模式就是多路复用,我们的应用如何能够利用好多路复用IO呢?经过前人多年实践总结,搞了一个Reactor模式,目前应用非常广泛,著名的Netty、Tomcat NIO就是基于这个模式。
Reactor的核心是事件分发器和事件处理器,事件分发器是连接多路复用IO和网络数据处理的中枢,核心就是监听Socket事件(select/epoll_wait),然后将事件分发给事件处理器,事件分发器和事件处理器都可以基于线程池来做。
需要重点提一下的是,在Socket事件中主要有两大类事件,一个是连接请求,另一个是读写请求,连接请求成功处理之后会创建新的Socket,读写请求都是基于这个新创建的Socket。
所以在网络处理场景中,实现Reactor模式会稍微有点绕,但是原理没有变化。具体实现可以参考Doug Lea的《Scalable IO in Java》(http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf)
电商项目怎样处理或用啥技术解决高负载、高并发、高可用性问题

Reactor原理图
\u0026gt;\u0026gt;\u0026gt;\u0026gt;0x0C Nginx多进程模型
Nginx默认采用的是多进程模型,Nginx分为Master进程和Worker进程,真正负责监听网络请求并处理请求的只有Worker进程,所有的Worker进程都监听默认的80端口,但是每个请求只会被一个Worker进程处理。
这里面的玄机是:每个进程在accept请求前必须争抢一把锁,得到锁的进程才有权处理当前的网络请求。每个Worker进程只有一个主线程,单线程的好处是无锁处理,无锁处理并发请求,这基本上是高并发场景里面的最高境界了。(参考http://www.dre.vanderbilt.edu/~schmidt/PDF/reactor-siemens.pdf)
数据经过网卡、操作系统、网络协议中间件(Tomcat、Netty等)重重关卡,终于到了我们应用开发人员手里,我们如何处理这些高并发的请求呢?我们还是先从提升单机处理能力的角度来思考这个问题。
\u0026gt;\u0026gt;\u0026gt;\u0026gt;0x0D 突破木桶理论
据经过网卡、操作系统、中间件(Tomcat、Netty等)重重关卡,终于到了我们应用开发人员手里,我们如何处理这些高并发的请求呢?
我们还是先从提升单机处理能力的角度来思考这个问题,在实际应用的场景中,问题的焦点是如何提高CPU的利用率(谁叫它发展的最快呢),木桶理论讲最短的那根板决定水位,那为啥不是提高短板IO的利用率,而是去提高CPU的利用率呢?
这个问题的答案是在实际应用中,提高了CPU的利用率往往会同时提高IO的利用率。当然在IO利用率已经接近极限的条件下,再提高CPU利用率是没有意义的。我们先来看看如何提高CPU的利用率,后面再看如何提高IO的利用率。
\u0026gt;\u0026gt;\u0026gt;\u0026gt;0x0E 并行与并发
提升CPU利用率目前主要的方法是利用CPU的多核进行并行计算,并行和并发是有区别的,在单核CPU上,我们可以一边听MP3,一边Coding,这个是并发,但不是并行,因为在单核CPU的视野,听MP3和Coding是不可能同时进行的。
只有在多核时代,才会有并行计算。并行计算这东西太高级,工业化应用的模型主要有两种,一种是共享内存模型,另外一种是消息传递模型。
\u0026gt;\u0026gt;\u0026gt;\u0026gt;0x0F 多线程设计模式
对于共享内存模型,其原理基本都来自大师Dijkstra在半个世纪前(1965)的一篇论文《Cooperating sequential processes》,这篇论文提出了大名鼎鼎的概念信号量,Java里面用于线程同步的wait/notify也是信号量的一种实现。
大师的东西看不懂,学不会也不用觉得丢人,毕竟大师的嫡传子弟也没几个。东洋有个叫结城浩的总结了一下多线程编程的经验,写了本书叫《JAVA多线程设计模式》,这个还是挺接地气(能看懂)的。下面简单介绍一下。


推荐阅读