您当前的位置:首页 > 新闻 > 科技

【实用技巧篇】高并发应用程序的设计原理和模式

时间:2020-03-30 16:36:35  来源:  作者:

1.概述

在本文中,我们将讨论为建立高度并发的应用程序而逐渐建立的一些设计原理和模式。

但是,值得注意的是,设计并发应用程序是一个广泛而复杂的主题,因此,没有任何教程可以声称对它的处理是详尽无遗的。我们这里将介绍一些常用的技巧!

2.并发基础

在继续进行之前,先来了解基础知识。首先,我们必须阐明我们对所谓的并发程序的理解:如果同时进行多个计算,则我们将程序称为并发程序。

现在,请注意,我们已经提到了计算是同时发生的,也就是说,它们是同时进行的。但是,它们可能同时执行或不同时执行,了解差异是很重要的,因为同时执行的计算称为parallel

2.1 如何创建并发模块?

了解我们如何创建并发模块很重要。有很多选项,但我们将在此处重点介绍两个流行的选择:

  • 进程:进程是正在运行的程序的实例,该程序与同一计算机中的其他进程隔离。机器上的每个进程都有自己独立的时间和空间。因此,通常不可能在进程之间共享内存,并且它们必须通过传递消息进行通信。
  • 线程:另一方面,线程只是进程的一部分,一个程序中可以有多个线程共享同一内存空间。但是,每个线程都有唯一的堆栈和优先级。线程可以是本地线程(由操作系统本地调度)或绿色(由运行时库调度)。

2.2 并发模块如何交互?

如果并发模块不必通信,这是非常理想的,但是通常不是这种情况。这产生了两种并发编程模型:

  • 共享内存:在此模型中,并发模块通过在内存中读写共享对象进行交互。这通常导致并发计算的交错,从而导致竞争条件。因此,它可以不确定地导致不正确的状态。
【实用技巧篇】高并发应用程序的设计原理和模式

 

  • 消息传递:在此模型中,并发模块通过通过通信通道相互传递消息来进行交互。在这里,每个模块顺序处理传入的消息。由于没有共享状态,因此编程相对容易一些,但这仍然无法摆脱竞争条件!
【实用技巧篇】高并发应用程序的设计原理和模式

 

2.3 并发模块如何执行?

自从摩尔定律在处理器的时钟速度方面碰壁以来已经有一段时间了。取而代之的是,由于必须增长,因此我们开始将多个处理器打包到同一芯片上,通常称为多核处理器。但是,听到具有32个以上内核的处理器并不罕见。

现在,我们知道单个内核一次只能执行一个线程或一组指令。但是,进程和线程的数量可以分别为数百和数千。那么,它如何真正起作用?这是操作系统为我们模拟并发的地方。操作系统通过时间分片来实现这一点-这实际上意味着处理器会频繁地,不可预测地且不确定地在线程之间切换。

3.并行编程中的问题

在很大程度上,我们在并行编程方面的经验涉及将本机线程与共享内存一起使用。因此,我们将专注于由此产生的一些常见问题:

  • 互斥(同步基元):交织线程需要对共享状态或内存具有独占访问权限,以确保程序的正确性。共享资源的同步是一种实现互斥的流行方法。有几种同步原语可供使用-例如,锁,监视器,信号灯或互斥锁。但是,互斥编程很容易出错,通常会导致性能瓶颈。与死锁和活锁相关的问题有很多讨论的。
  • 上下文切换(重量级线程):每个操作系统都有本机(尽管有所不同)对进程和线程等并发模块的支持。如讨论的那样,操作系统提供的基本服务之一是调度线程,以便通过时间分片在有限数量的处理器上执行。现在,这实际上意味着线程经常在不同状态之间切换。在此过程中,需要保存并恢复其当前状态。这是一项耗时的活动,直接影响整体吞吐量。

4.高并发设计模式

现在,我们了解了并发编程的基础知识以及其中的常见问题,是时候了解一些避免这些问题的常见模式了。我们必须重申,并发编程是一项艰巨的任务,需要大量经验。因此,遵循某些已建立的模式可以使任务更容易。

4.1 基于Actor的并发

我们将针对并发编程讨论的第一个设计称为Actor模型。这是并行计算的数学模型,基本上将一切都视为参与者。参与者可以相互传递消息,并且响应消息可以做出本地决策。这是由卡尔·休伊特(Carl Hewitt)首次提出的,并启发了许多编程语言。

Scala用于并发编程的主要构造是参与者。Actor是Scala中的普通对象,我们可以通过实例化Actor类来创建。此外,Scala Actors库提供了许多有用的actor操作:

class myActor extends Actor {
    def act() {
        while(true) {
            receive {
                // Perform some action
            }
        }
    }
}

在上面的示例中,在无限循环内对receive方法的调用将使actor挂起,直到消息到达为止。到达后,邮件将从参与者的邮箱中删除,并采取了必要的措施。

【实用技巧篇】高并发应用程序的设计原理和模式

 

actor模型消除了并发编程的基本问题之一-------共享内存。参与者通过消息进行通信,并且每个参与者依次处理其专用邮箱中的消息。但是,我们通过线程池执行角色,而且我们已经看到,本地线程可能是重量级的,因此数量有限。

当然,这里还有其他模式可以为我们提供帮助,稍后将介绍这些模式!

4.2 基于事件的并发

基于事件的设计明确解决了本机线程生成和操作成本高昂的问题。基于事件的设计之一是事件循环。事件循环与事件提供程序和一组事件处理程序一起使用。在这种设置中,事件循环在事件提供程序上阻塞,并在到达时将事件调度到事件处理程序

基本上,事件循环不过是事件分配器!事件循环本身可以仅在单个本机线程上运行。那么,事件循环中到底发生了什么?让我们来看一个非常简单的事件循环的伪代码作为示例:

while(true) {
    events = getEvents();
    for(e in events)
        processEvent(e);
}

基本上,我们的事件循环所要做的就是不断寻找事件,并在发现事件后对其进行处理。该方法确实很简单,但可以从事件驱动的设计中受益。

使用此设计构建并发应用程序可为应用程序提供更多控制。而且,它消除了多线程应用程序的一些典型问题,例如死锁。

【实用技巧篇】高并发应用程序的设计原理和模式

 

JAVAScript实现事件循环以提供异步编程。它维护一个调用堆栈以跟踪要执行的所有功能。它还维护一个事件队列,用于发送新功能进行处理。事件循环不断检查调用堆栈,并从事件队列中添加新功能。所有异步调用都会分派到通常由浏览器提供的Web API。

事件循环本身可以在单个线程上运行,但是Web API提供了单独的线程。

4.3 非阻塞算法

在非阻塞算法中,一个线程的挂起不会导致其他线程的挂起。我们已经看到,我们的应用程序中只能有数量有限的本机线程。现在,阻塞在线程上的算法明显降低了吞吐量, 并阻止了我们构建高度并发的应用程序。

非阻塞算法始终使用底层硬件提供的比较交换原子原语。这意味着硬件将比较存储位置的内容与给定值,并且只有它们相同时,才会将值更新为新的给定值。这看起来很简单,但实际上为我们提供了一个原子操作,否则将需要同步。

这意味着我们必须编写使用此原子操作的新数据结构和库。这为我们提供了多种语言的大量免等待和免锁实现。Java具有几种非阻塞数据结构,例如AtomicBoolean,AtomicInteger,AtomicLong和AtomicReference。

考虑一个有多个线程试图访问相同代码的应用程序:

boolean open = false;
if(!open) {
    // Do Something
    open=false;
}

显然,上面的代码不是线程安全的,并且它在多线程环境中的行为可能是不可预测的。我们的选择是将这段代码与锁同步,或者使用原子操作:

AtomicBoolean open = new AtomicBoolean(false);
if(open.compareAndSet(false, true) {
    // Do Something
}

如我们所见,使用像AtomicBoolean这样的非阻塞数据结构可以帮助我们编写线程安全的代码,而不会沉迷于锁的弊端!

5.支持编程语言

我们已经看到,可以通过多种方式构造并发模块。尽管编程语言确实有所作为,但主要是底层操作系统如何支持该概念。但是,由于本机线程支持的基于线程的并发在可伸缩性方面遇到了新的障碍,因此我们始终需要新的选择。

我们可以使用的一种解决方案是绿色线程。绿色线程是由运行时库调度的线程,而不是由底层操作系统本地调度的线程。尽管这并不能解决基于线程的并发中的所有问题,但在某些情况下,它肯定可以为我们提供更好的性能。

现在,除非我们选择使用的编程语言支持绿色线程,否则使用绿色线程并非易事。并非每种编程语言都具有此内置支持。同样,我们可以通过不同的编程语言以非常独特的方式来实现我们所谓的绿色线程。让我们来看一些可用的选项。

5.1 Go中的Goroutines

Go编程语言中的Goroutine 是轻量级线程。它们提供可以与其他功能或方法同时运行的功能或方法。Goroutines 非常便宜,因为它们从开始只占用几千字节的堆栈大小

最重要的是,goroutines与较少数量的本机线程复用。此外,goroutine使用通道相互通信,从而避免了对共享内存的访问。我们几乎获得了所需的一切,然后猜测-什么都不做!

5.2 Erlang中的进程

在Erlang中,每个执行线程称为一个进程。但是,这与我们到目前为止讨论的过程不太一样!Erlang进程重量轻,内存占用少,并且创建和处理速度快,调度开销低。

在幕后,Erlang进程不过是运行时为之调度的功能。而且,Erlang进程不共享任何数据,它们通过消息传递相互通信。这就是为什么我们首先称这些“过程”的原因!

5.3 Java中的Fiber(提案)

Java并发的故事一直在不断发展。Java确实从一开始就对绿色线程(至少对Solaris操作系统)提供了支持。但是,由于障碍超出了本教程的范围,因此已停止使用。

从那时起,Java中的并发全部与本地线程有关,以及如何巧妙地使用它们!但是出于显而易见的原因,我们可能很快就会在Java中有了一个新的并发抽象,称为光纤。Project Loom建议将延续与纤维一起引入,这可能会改变我们用 Java 编写并发应用程序的方式

这只是对不同编程语言中可用功能的简要介绍。其他编程语言还尝试了更多有趣的方式来处理并发。

此外,值得注意的是,在设计高度并发的应用程序时,上一节中讨论的设计模式与编程语言对类似绿线程的抽象的支持的组合可能会非常强大。

6.高并发应用

实际应用程序通常具有多个组件,这些组件通过导线相互交互。我们通常通过Internet对其进行访问,它包含多种服务,例如代理服务,网关,Web服务,数据库,目录服务和文件系统。

在这种情况下,我们如何确保高并发性?让我们探索其中的一些层以及构建高度并发应用程序所具有的选项。

构建高并发应用程序的关键是使用此处讨论的一些设计概念。我们需要为工作选择合适的软件-----已经结合了其中一些实践的软件。

6.1 网页层

Web通常是用户请求到达的第一层,因此在此处不可避免地需要进行高并发性设置。让我们看看其中的一些选项:

  • Node(也称为NodeJS或Node.js)是基于Chrome的V8 JavaScript引擎构建的开源,跨平台JavaScript运行时。在处理异步I / O操作时,Node工作得很好。Node之所以如此出色,是因为它在单个线程上实现了一个事件循环。借助回调的事件循环可异步处理所有阻塞操作,例如I / O。
  • Nginx一个开放源代码的Web服务器,除其他用法外,我们通常将用作反向代理。nginx提供高并发性的原因是它使用了异步的,事件驱动的方法。nginx在一个线程中与主进程一起运行。主流程维护执行实际处理的工作流程。因此,工作进程同时处理每个请求。

6.2 应用层

在设计应用程序时,有多种工具可帮助我们构建高并发性,先检查一下其中一些可用的库和框架

  • Akka用Scala编写的工具包,用于在JVM上构建高度并发和分布式的应用程序。Akka处理并发的方法基于我们前面讨论的参与者模型。Akka在参与者和基础系统之间创建了一层。该框架处理创建和调度线程,接收和调度消息的复杂性。
  • Project Reactor 是一个反应式库,用于在JVM上构建非阻塞应用程序。它基于Reactive Streams规范,专注于有效的消息传递和需求管理(背压)。反应堆操作员和调度程序可以维持较高的消息吞吐率。几个流行的框架提供了Reactor的实现,包括Spring WebFlux和RSocket。
  • Netty是一个异步的,事件驱动的网络应用程序框架。我们可以使用Netty开发高度并发的协议服务器和客户端。Netty利用了 NIO,它是Java API的集合,可通过缓冲区和通道提供异步数据传输。它为我们提供了多个优势,例如更好的吞吐量,更低的延迟,更少的资源消耗以及最小化不必要的内存复制

6.3 资料层

没有数据就没有完整的应用程序,数据来自持久性存储。当我们讨论有关数据库的高并发性时,大多数重点仍放在NoSQL系列上。这主要是由于NoSQL数据库可以提供线性可伸缩性,但是在关系型变量中却很难实现。让我们看一下数据层的两个流行工具:

  • Cassandra是一个免费的开源NoSQL分布式数据库,可在商品硬件上提供高可用性,高可伸缩性和容错能力。但是,Cassandra不提供跨越多个表的ACID事务。因此,如果我们的应用程序不需要强一致性和事务性,那么我们可以受益于Cassandra的低延迟操作。
  • Kafka是一个分布式流媒体平台。Kafka将记录流存储在称为主题的类别中。它可以为记录的生产者和使用者提供线性水平可伸缩性,同时提供高可靠性和耐用性。分区,副本和代理是它提供大规模分布式并发的一些基本概念。

6.4 缓存层

现代世界中没有任何旨在实现高并发性的Web应用程序能够承受每次访问数据库的负担。这就让我们选择了一个缓存-----最好是可以支持我们高度并发的应用程序的内存中缓存:

  • Hazelcast 是一个分布式,云友好的,内存中的对象存储和计算引擎,支持多种数据结构,如地图,设置,列表,多重映射, RingBuffer和 HyperLogLog。它具有内置的复制功能,并提供高可用性和自动分区。
  • redis 是一种内存数据结构存储,我们主要将其用作缓存。它提供了一个内存键值数据库,具有可选的持久性。支持的数据结构包括字符串,哈希,列表和集合。Redis具有内置的复制功能,并提供高可用性和自动分区。如果我们不需要持久性,Redis可以为我们提供功能丰富,网络化的内存中缓存,并具有出色的性能。

当然,在我们追求构建高度并发的应用程序时,我们几乎没有涉及任何可用的内容。重要的是要注意,除可用软件外,我们的要求还应指导我们创建适当的设计。这些选项中的某些选项可能适用,而其他选项可能不合适。

而且,别忘了还有更多可用的选项可能更适合我们的要求。

7.结论

在本文中,我们讨论了并发编程的基础。我们了解了并发的一些基本方面及其可能导致的问题。此外,我们演示了一些设计模式,这些模式可以帮助我们避免并发编程中的典型问题。

最后,我们介绍了一些可用于构建高度并行的端到端应用程序的框架,库和软件。

读者福利

分享一份自己整理好的Java学习资料,里面包含了:分布式架构、高可扩展、高性能、高并发、Jvm性能调优、Spring,MyBatis,Nginx源码分析,Redis,ActiveMQ、、Mycat、Netty、Kafka、MySQL、Zookeeper、TomcatDocker、Dubbo、Nginx等多个知识点高级进阶干货

 

【实用技巧篇】高并发应用程序的设计原理和模式

 

 

【实用技巧篇】高并发应用程序的设计原理和模式

 

 

【实用技巧篇】高并发应用程序的设计原理和模式

 

 

 



Tags:高并发应用程序   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
1.概述在本文中,我们将讨论为建立高度并发的应用程序而逐渐建立的一些设计原理和模式。但是,值得注意的是,设计并发应用程序是一个广泛而复杂的主题,因此,没有任何教程可以声称对...【详细内容】
2020-03-30  Tags: 高并发应用程序  点击:(71)  评论:(0)  加入收藏
▌简易百科推荐
非法购买公民信息、开发人脸认证规避技术……今年年初,广东省公安厅网安部门侦破全国首例破解“青少年防沉迷系统”的新型网络犯罪案件,抓获犯罪嫌疑人13名,查处非...【详细内容】
2021-12-28    人民日报客户端  Tags:数据安全步   点击:(5)  评论:(0)  加入收藏
就在今天,腾讯方面宣布将在2022年1月31日下架企业QQ和营销QQ,其实这一消息的降临并不让笔者意外,因为早在今年的10月28日20点之后,企业QQ和营销QQ就被停止了续费服务。相信很多...【详细内容】
2021-12-27  科技探险家    Tags:企业QQ   点击:(22)  评论:(0)  加入收藏
日前,上海交通大学发布《全球电竞之都评价报告》,对全球15个致力于发展电竞之都的城市进行评价,上海作为中国城市电竞发展的排头兵,其拥有众多优质电竞企业及完整产业集群,因此排...【详细内容】
2021-12-27  经济日报    Tags:电竞   点击:(3)  评论:(0)  加入收藏
为优化网络氛围环境,微博又开始整顿用户信息了。本月月初,微博官方发布公告,要求昵称中带有如“二货”“SB”“瘪三”“娘炮”等明显低俗或侮辱性词汇的用户尽快修改,否则将面临...【详细内容】
2021-12-24  运了个营    Tags:微博   点击:(10)  评论:(0)  加入收藏
昨日谷歌宣布,自2022年12月19日开始停止对OnHub的软件支持,OnHub路由器仍将提供Wi-Fi信号,但用户无法用谷歌Home应用程序管理它。无法更新Wi-Fi网络设置、添加额外的Wifi设备或...【详细内容】
2021-12-22  雷峰网    Tags:Google OnHub   点击:(5)  评论:(0)  加入收藏
IT之家 12 月 20 日消息,百度网盘青春版 iOS 客户端今日晚间率先开启内测,安卓客户端将在稍后内测。使用苹果 iPhone 的IT之家小伙伴可以点此下载内测版,需要先下载 TestFlight...【详细内容】
2021-12-21  IT之家    Tags:百度网盘   点击:(10)  评论:(0)  加入收藏
对于拼车单,是接还是不接,不少网约车司机表示很矛盾。接吧,钱少事多,常常跑了个寂寞,不接吧,车多客少,挑三拣四没饭吃。 在平台大力推广拼车单之下,不少司机迫于生活压力,最终还是打...【详细内容】
2021-12-17  网约车情报分享    Tags:滴滴   点击:(9)  评论:(0)  加入收藏
蓝鲸TMT频道12月16日讯,据饿了么官方微信公众号,近日,在圆桌会上,蓝骑士与平台交流了配送安全问题。饿了么表示,线上将技术手段融入安全防护;线下将持续进行安全培训,并试点智能头...【详细内容】
2021-12-17    金融界  Tags:饿了么   点击:(24)  评论:(0)  加入收藏
开源最前线(ID:OpenSourceTop) 猿妹编译项目地址: https://github.com/restic/restic全球知名代码托管平台 GitHub 今天就重磅发布了今年的年度报告——《2021 年度 O...【详细内容】
2021-12-17  Python部落    Tags:   点击:(9)  评论:(0)  加入收藏
新京报快讯 据中国网络视听节目服务协会网站消息,12月15日,中国网络视听节目服务协会发布了《网络短视频内容审核标准细则》(2021)。中国网络视听节目服务协会组织有关短视频平...【详细内容】
2021-12-16    新京报  Tags:短视频   点击:(11)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条