反应式编程是一种基于异步数据流和基于事件的实时处理的编程范式。这意味着操作并不会等待彼此同步完成。它支持非阻塞操作,并允许通过观察事件实时异步执行其他操作。反应式编程通过在运行时监控其他进程的执行情况来实现现实事件和异步执行。
现如今许多应用程序都需要能处理大量并发/同步请求。因此,传统方法不足以处理这些操作。所以我们向着以最有效果的方式使用硬件来开发软件的原则迈进.服务器端响应式编程是一种提高web应用程序或提高服务器端应用程序的性能和可扩展性的方法。这种结构使服务器端应用程序能够处理多个请求,提高性能的同时处理高用户流量。
如今,微服务、云原生应用程序和分布式系统相当普遍,更有效的使用资源和低延迟非常重要。响应式编程通过允许非阻塞操作和基于事件的实时执行为这些问题提供了解决方案。
异步:执行一项任务而不等待其结果并同时继续执行其他任务的能力。
数据流:随时间顺序发生的一系列事件。流为我们提供值、错误和完成等信号。
背压: 用于确保数据流速度和处理能力之间兼容性的概念。
反应式编程通过观察和监听事件并对它们做出反应来进行,这可以通过观察者设计模式来实现。
背压是什么意思?
背压是指控制系统中数据处理速率的能力。当系统接收到的数据超出其处理能力时,它可以向源发出信号以减慢或调节数据流。这是维持系统稳定的重要特性,也是反应式编程的优点之一。
传统编程
命令式编程,是一种编程范式,其中程序员明确告诉计算机要采取哪些步骤来解决问题。在这些方法中,通过为线程池中的每个请求分配单独的线程来处理请求。但是线程池的容量限制了可以同时处理请求的数量。这种方式会导致每个线程遇到I/O操作时被阻塞,导致等待并增加资源占用。断路器可以缓解其中的一些问题,但是还是远远不够。
当请求数量增大时,同步的阻塞结构也会影响性能。此外,这种方法并没有优化系统资源占用,因为可能需要新的实例来处理高流量,这可能会带来高昂的成本。命令式编程还缺乏对背压机制的支持该机制可以防止负载突然增加时出现系统故障。
传统命令式编程应用程序的一般特征:
- 同步和阻塞 →请求被同步和阻塞处理。当发出请求时,会为其分配一个线程,并在返回响应之前等待任何 I/O 操作完成。该线程对于其他任务保持阻塞状态,并且可以在操作完成后返回响应。
- 每个请求一个线程 →为每个请求分配一个线程也会限制传入请求的数量。系统只能处理与线程池大小一样多的请求。此外,大量请求也会影响性能。
- 系统资源利用率低 →在同步和阻塞模式下,为了在大流量下处理一定数量的请求,需要创建新的实例。就资源使用而言,这是一项成本高昂的操作。
- 缺乏对反压机制的支持 →如果请求突然增加,可能会出现服务器或客户端中断的情况。此后,用户将无法访问该应用程序。我们将更详细地讨论背压,但它可以被描述为一种防止系统在负载突然增加时中断的机制。
每个线程都会消耗一定量的内存。为了在高流量下的应用程序中获得良好的性能,需要高内存大小。水平扩展可以通过像 Kubernetes 这样的结构来完成。这种方法目前是很好的解决方案之一,将来会继续使用,但是,每次流量增加时创建新实例也会在成本和复杂性方面产生其他问题。
考虑到成本和扩展问题,每个实例都有成本,作为工程师,我们倾向于事半功倍。为了解决这些类型的问题并产生更好的结果,我们可以通过更少的内存使用和更少的实例来实现更有效的可扩展性。
深入探讨响应式编程
响应式编程并不是一种新的编程范式,而是新近流行的编程范式。
- 它专门为了改进异步和非阻塞操作而定制。它通过事件/消息驱动的流创建数据流。
- 响应式编程与 (!=) 函数式编程不同。您可以通过结合反应式编程和函数式编程来创造伟大的事物。
- 数据流中提供背压支持。
- 由于其异步和非阻塞结构,它提供了可预测的响应时间。
- 它可以更好地利用系统资源。线程不会被阻塞,应用程序将能够以更少的线程有效地服务更多的用户。
响应式编程是如何工作的?
在反应式编程中,关键是使用基于事件的流来管理数据。事件、消息、调用,甚至错误都是通过数据流传输的。通过反应式编程,这些流程会被不断观察并直接响应值的变化,执行下一个操作。
在编写应用程序时,应该从任何事务创建数据流:用户操作、HTTP请求、收到的消息、要发送的消息、通知、变量变更、缓存事件、数据库操作;你可以说是任何事件的改变或发生的事情。
反应式编程中,为了从数据源获得每个结果创建一个事件或消息。数据源可以是外部服务、数据库或文件。如果数据源完成或收到错误,则会创建事件或消息。因此,在这两种情况下,我们都存在一个事件。
当对数据库进行查询时,服务立即返回,并且一旦准备好,数据就会通过流推送。为每个数据元素创建一个事件。数据流通过OnComplete完成。
发生错误时会发生什么?
流中发生的每个事件或消息都对应一个事件或消息。因此,发生错误也作为事件发生。
获取项目时,如果遇到错误,则会将其作为事件传递给onError。我们还可以在onError部分解决如何处理异常。
当我们查询数据库没有结果时,onComplete事件仍然发生。
对于注册,我们发送注册请求,如果调用快速响应并成功完成,我们可以通过 onComplete 事件来了解这一点。
- onNext,我们可以在流式传输时继续下一个项目。
- onComplete表示成功完成
- onError表示错误情况。
背压支持
例如,我们有一个从另一个服务接收数据的客户端应用程序。服务可以以100x的速率发送事件,而客户端应用程序只能以20x的速率处理事件。在这种情况下客户端应用程序可能会因负载过大而出现性能损失甚至中断。借助背压,客户端应用程序可以通知服务器它只能以20倍的速率处理数据,并且服务只能以20倍的速率发送数据。这样,客户端就可以继续以其能够处理的负载量高效工作。
流程的管理方式与流API中的lambda操作类似。因此函数式编程与反应式编程配合的很好。
标签:请求,什么,编程,应用程序,线程,反应式,事件 From: https://www.cnblogs.com/wuhaoxin/p/18112518