浅谈Java响应式系统

初识响应式系统

ReactiveX的本质就是Observer+Iterator+函数编程+异步。是一个事件驱动的,异步的,可观察的序列。

使用RxJava可以将异步的回调改写成为链式调用。在代码上看起来非常简洁明了。当然JDK也提供了CompletionStage提供了类似的解决回调的功能。

Rxjava只是一个java的基本库,如果我们想要构建响应式的服务器,响应式的web,响应式的数据访问,甚至是响应式的微服务,又该如何处理呢?

这个时候我了解到了Vert.x。Vert.x就是用来构建Reactive的应用程序的。

Vert.x是Eclipse基金会旗下的产品,基于事件驱动和非阻塞编程。

Vert.x是模块化的,里面有Core,web,Data access,Reactive,Microservices,MQTT,Authentication and Authorisation,Messaging,Event bus Bridge,Devops,Testing,Clustering,Services和Cloud等模块。可谓是应有尽有。

其实java界一直都在向reactive靠近,除了JDK本身的api新特性意外,比如业界有名的Spring也在spring 5中添加了webflux框架,这就是一款reactive的web框架。

什么是响应式系统

在上一节我们提到了Rxjava和Vert.x,里面有一些共同的关键字,比如异步,事件驱动,观察者模式,函数式编程,消息驱动等,所有的一切都是为了让现代系统更加健壮,运行的更快,更加富有弹性,从而更好。

系统从很久之前的单一服务器,到现在的多服务器架构,从秒级响应到现在的毫秒级响应。从90%可用都现在的99.999%可用。不论从系统设计,架构还是程序编码都发生了极大的变化。

我们迫切的需要一个能够满足以上需求的通用的系统架构解决方案。

那么什么是响应式系统呢?

响应式系统需要具备这些特征:及时响应性(Responsive)、恢复性(Resilient)、有弹性(Elastic)以及消息驱动(Message Driven)。我们把具有上面四个特性的系统就叫做响应式系统。

上面的四个特性中,及时响应性(Responsive)是系统最终要达到的目标,恢复性(Resilient)和有弹性(Elastic)是系统的表现形式,而消息驱动(Message Driven)则是系统构建的手段。

于是我们得到了响应式系统的终极架构图:

使用响应式系统的架构,可以保证系统的可维护性,和可扩展性,并且在系统出现问题的时候能够有更好的可容忍性。

响应式系统的四大特点

在定义响应式系统的时候,我们提到了及时响应性(Responsive)、恢复性(Resilient)、有弹性(Elastic)以及消息驱动(Message Driven)这四大特点。

接下来我们将会具体描述这四大特点到底有什么奥秘。

及时响应性(Responsive)

Responsive就是系统能够立刻响应请求,这应该包含两个方面的含义。

第一,响应请求的时间要够短,如果用户请求一个页面,等待2秒钟估计已经是极限了。再长的时间估计就要失去这个用户了。

时代在变,技术也在变,十几年前下载一个几百K的文件要一分钟估计就算是很快了,现在没有个几M每秒,肯定会让人抓狂不已。

在现代CPU,服务集群和光纤传输的飞速发展和页面承载信息的巨大变化,一个普通的页面可能就要包含十几二十个请求。每个请求的时间已经提升到了毫秒甚至是微妙级。同时在页面展示方面也产生了很多新的变化,比如异步加载和预加载等技术。

最终是为了创建一个能够及时响应的系统。而系统背后的各种技术和新的请求方式都是为这个目标来服务的。

第二,对于错误的响应时间要短。

一方面对于用户来说,要及时的提醒用户可能出现的错误。不管是系统本身的错误亦或是用户的使用错误,都需要在一个有限的时间内进行响应。

另一方面,对于系统本身来说,要能够快速的定位和响应问题。这是提升系统本身的稳定性和安全性的基本要求。

如何发现和响应系统本身的问题呢?第一要有完善的错误记录系统,让一切都有章可循。第二就是要有相应的监控措施,让系统出现的任何问题都能够及时的进行通知和报警。

恢复性(Resilient)

可恢复性是指系统在遇到失败或者错误时仍然能够对外提供服务。

首先,要求我们的系统足够稳健,能够抗住正常的访问,并且能够可预见的应对热点访问。

其次,现代系统的功能是各种各样的,一个简单的APP的后台可能有多达几十种服务。所以我们需要区分出来哪些是关键的服务,哪些是非关键的服务。对于关键的服务我们一定要确保其的稳定性,对于非关键性的服务,我们可以在首先保障关键服务的前提下再进行考虑。

比如说一个订单系统,下单肯定就是关键服务了,而商品的点赞数,评论等则就没有那么重要。

区分好了关键服务和非关键服务,就要对他们进行区分和隔离。非关键服务的任何错误或者异常都不能够影响到关键服务。

再次,如果服务发送了错误,我们应该尽可能的缩小影响范围,不要一点小错误影响所有的服务。

最后,对于失败要有恢复措施,并且这个恢复措施不能够影响其他的系统服务。比如我们可以对现有的系统做一个复制,在某个服务失败的时候,可以用备用的服务进行替代。

只有这样,才能够保证系统的可靠性。

有弹性(Elastic)

弹性的意思就是在需要的时候服务可以动态扩展,在不需要的时候可以停用服务以节约资源。

现在很多云服务都提供了动态扩展的功能,如果系统是我们自己实现的,那就需要区分出热点问题和非热点问题。

只有热点问题才需要考虑弹性,系统不能有瓶颈,并且能够进行分片或者复制,从而实现分布式的动态负载功能。

负载均衡技术可能是我们最常用的弹性功能,但是如何动态的自动的进行负载的均衡可能是一个非常有意义的话题。

弹性可以通过软件或者硬件的方式来实现,当然我们需要在成本和效果之间达成一个平衡。

消息驱动(Message Driven)

消息驱动的本质就是发送消息,接收消息然后进行处理。现在大型系统很少有不使用消息中间件的。使用这些消息中间件的好处就是可以解耦和异步驱动。

异步的好处这里就不多讲了,大概就是不用一直傻傻的等待,而是充分利用时间去做更有效率的事情。

解耦的作用就更大了,现代系统基本上都是由很多个服务组成的。要想保证这么多系统的平稳运行,肯定要做解耦操作,否则一个服务的失败就会导致所有服务的不可用,想想都觉得害怕。

而消息驱动,就是这些不同的服务组件之间沟通的桥梁。告诉他们要做什么,等待他们的反馈消息。

或者我们可以把这些服务看做一个一个的人,多人之间的沟通就是通过语言。语言驱动或者也可以叫做消息驱动。

这里再讲一个消息驱动中常见的一个概念:back-pressure。

我们知道发送消息和接收消息的服务其处理速度是有限的,当发送消息的速度快过与接收消息的速度时候,就会发送消息阻塞,当消息阻塞过多的时候,就有可能发送消息丢失或者服务崩溃的情况。并且如果太多消息一直都没有被处理,没有得到响应的话,对于用户体验也是非常不好的。

这里就需要使用到back-pressure的概念,如果消息接收方消息处理不过来,则可以通知消息发送方,告知其正在承受压力,需要降低负载。back-pressure是一种消息反馈机制,从而使系统得以优雅地响应负载, 而不是在负载下崩溃。

总结

reactive是近几年非常流行的一个概念,如何通过reactive来设计出满足我们需要的系统,是我们需要考虑的问题。

以上就是浅谈Java响应式系统的详细内容,更多关于Java响应式系统的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java并发编程之性能、扩展性和响应

    本文讨论的重点在于多线程应用程序的性能问题.我们会先给性能和扩展性下一个定义,然后再仔细学习一下Amdahl法则.下面的内容我们会考察一下如何用不同的技术方法来减少锁竞争,以及如何用代码来实现. 1.性能 我们都知道,多线程可以用来提高程序的性能,背后的原因在于我们有多核的CPU或多个CPU.每个CPU的内核都可以自己完成任务,因此把一个大的任务分解成一系列的可彼此独立运行的小任务就可以提高程序的整体性能了.可以举个例子,比如有个程序用来将硬盘上某个文件夹下的所有图片的尺寸进行修改,应用多线程技

  • JavaWeb Refresh响应头代码实例详解

    这篇文章主要介绍了JavaWeb Refresh响应头代码实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.Refresh响应头:可以理解为定时的重定向,在指定的时间后发生页面的跳转 二.代码示例: package cn.xxx.Servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.Ht

  • java web请求和响应中出现中文乱码问题的解析

    说明:在计算机中保存的一切文本信息是以一定的编码表(0,1,0,1)来保存我们所认识的字符(汉字或英文字符),由字符到计算机存储的二进制过程是编码,由读取二进制到文本的过程称为解码.而字符编码有多种不同的编码表,所以,如果编码格式和解码格式不是同一个码表就会出现乱码.想要避免出现乱码,需要使保存和读取时使用相同的码表. 在java web编程中经常会出现乱码,现在详细讲解一下如何进行设置,避免乱码 1 网页编码 在编写网页的时候,需要指定网页的编码格式,使用<meta http-equiv=&quo

  • javaweb如何实现请求和响应

    先来看一个流程图: 服务器处理请求的流程: (1)服务器每次收到请求时,都会为这个请求开辟一个新的线程.   (2)服务器会把客户端的请求数据封装到request对象中,request就是请求数据的载体!   (3)服务器还会创建response对象,这个对象与客户端连接在一起,它可以用来向客户端发送响应. 由流程图可以看出,在JavaWeb的请求与响应中,最重要的两个参数为request以及response,这两参数在Servlet的service( )方法中. 1.response概念: r

  • java实现响应重定向发送post请求操作示例

    本文实例讲述了java实现响应重定向发送post请求操作.分享给大家供大家参考,具体如下: 关于重定向我们用的比较多的还是redirect:重定向,默认发送的get请求. return "redirect:/index"; 但有时候请求地址必须为post请求,比如security登录就只能接收post请求,下面来看一下如何后台如何发送post请求响应重定向. 首先可以定义一个map,用于存放参数键值对 Map<String, String> parameter = new

  • Java response响应体和文件下载实现原理

    通过response 设置响应体: 响应体设置文本: PrintWriter getWriter() 获得字符流,通过字符流的write(String s)方法可以将字符串设置到response 缓冲区中,随后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览 器端. 关于设置中文的乱码问题 原因:response缓冲区的默认编码是iso8859-1,此码表中没有中文,可以通过 response的setCharacterEncoding(String charset) 设

  • Android中通过RxJava进行响应式程序设计的入门指南

    错误处理 到目前为止,我们都没怎么介绍onComplete()和onError()函数.这两个函数用来通知订阅者,被观察的对象将停止发送数据以及为什么停止(成功的完成或者出错了). 下面的代码展示了怎么使用这两个函数: Observable.just("Hello, world!") .map(s -> potentialException(s)) .map(s -> anotherPotentialException(s)) .subscribe(new Subscrib

  • Java Web请求与响应实例详解

    Servlet最主要作用就是处理客户端请求并作出回应,为此,针对每次请求,Web容器在调用service()之前都会创建两个对象,分别是HttpServletRequest和HttpServletResponse.其中HttpServletRequest封装HTTP请求消息,HttpServletResponse封装HTTP响应消息.需要注意的是,Web服务器运行过程中,每个Servlet都会只创建一个实例对象,不过每次请求都会调用Servlet实例的service(ServletRequest

  • JavaFX桌面应用未响应问题解决方案

    日常使用软件的过程中,偶尔会遇到软件突然卡住,再点击几次就变成"未响应"的情况. 在JavaFX应用中同样也会出现这种情况,在开发过程中应该尽量避免这种情况的出现. 1. "未响应"重现 应用程序出现"未响应"这种情况往往是因为在UI线程中处理一些耗时的业务,当UI线程在处理耗时的业务时,UI就会卡住. 下面通过一个示例(获取Google页面title信息)来演示一下"未响应"这种情况. 这里使用 jsoup 来抓取Googl

  • 浅谈Java响应式系统

    初识响应式系统 ReactiveX的本质就是Observer+Iterator+函数编程+异步.是一个事件驱动的,异步的,可观察的序列. 使用RxJava可以将异步的回调改写成为链式调用.在代码上看起来非常简洁明了.当然JDK也提供了CompletionStage提供了类似的解决回调的功能. Rxjava只是一个java的基本库,如果我们想要构建响应式的服务器,响应式的web,响应式的数据访问,甚至是响应式的微服务,又该如何处理呢? 这个时候我了解到了Vert.x.Vert.x就是用来构建Rea

  • 浅谈Python响应式类库RxPy

    一.基本概念 Reactive X中有几个核心的概念,先来简单介绍一下. 1.1.Observable和Observer(可观察对象和观察者) 首先是Observable和Observer,它们分别是可观察对象和观察者.Observable可以理解为一个异步的数据源,会发送一系列的值.Observer则类似于消费者,需要先订阅Observable,然后才可以接收到其发射的值.可以说这组概念是设计模式中的观察者模式和生产者-消费者模式的综合体. 1.2.Operator(操作符) 另外一个非常重要

  • 浅谈Rx响应式编程

    目录 一.Observable 二.高阶函数 三.快递盒模型 3.1.快递盒模型1:fromEvent 3.2.快递盒模型2:interval 四.高阶快递盒 五.销毁快递盒 5.1.销毁快递盒--取消订阅 5.2.销毁高阶快递盒 六.补充 七.后记 一.Observable Observable从字面翻译来说叫做"可观察者",换言之就是某种"数据源"或者"事件源",这种数据源具有可被观察的能力,这个和你主动去捞数据有本质区别.用一个形象的比喻就

  • 浅谈Spring5 响应式编程

    近年来,响应式编程在开发者社区和客户中很受欢迎,由于其以声明的方式构建应用程序的能力,而不是强制,形成更加敏感和有弹性的应用.Spring 5 将反应系统纳入其核心框架的事实已经显示出向声明式编程的范式转变. 响应式编程管理数据生产者和消费者之间的异步数据流,它们需要以流畅的方式对数据进行响应.所以,响应式编程都是异步和事件驱动的流畅应用程序,需要少量的线程进行缩放. 响应式编程很难构建基于线程的架构,由于在基于共享可变状态.线程和锁的应用程序扩展过程中涉及到高度复杂性. 在响应式编程的上下文中

  • 浅谈Vue响应式(数组变异方法)

    前言 很多初使用Vue的同学会发现,在改变数组的值的时候,值确实是改变了,但是视图却无动于衷,果然是因为数组太高冷了吗? 查看官方文档才发现,不是女神太高冷,而是你没用对方法. 看来想让女神自己动,关键得用对方法.虽然在官方文档中已经给出了方法,但是在下实在好奇的紧,想要解锁更多姿势的话,那就必须先要深入女神的心,于是乎才有了去探索Vue响应式原理的想法.(如果你愿意一层一层地剥开我的心.你会发现,你会讶异-- 沉迷于鬼哭狼嚎 无法自拔QAQ). 前排提示,Vue的响应式原理主要是使用了ES5的

  • 浅谈Java并发编程之Lock锁和条件变量

    简单使用Lock锁 Java 5中引入了新的锁机制--java.util.concurrent.locks中的显式的互斥锁:Lock接口,它提供了比synchronized更加广泛的锁定操作.Lock接口有3个实现它的类:ReentrantLock.ReetrantReadWriteLock.ReadLock和ReetrantReadWriteLock.WriteLock,即重入锁.读锁和写锁.lock必须被显式地创建.锁定和释放,为了可以使用更多的功能,一般用ReentrantLock为其实例

  • 浅谈Java中IO和NIO的本质和区别

    IO的本质 IO的作用就是从外部系统读取数据到java程序中,或者把java程序中输出的数据写回到外部系统.这里的外部系统可能是磁盘,网络流等等. 因为对所有的外部数据的处理都是由操作系统内核来实现的,对于java应用程序来说,只是调用操作系统中相应的接口方法,从而和外部数据进行交互. 所有IO的本质就是对Buffer的处理,我们把数据放入Buffer供系统写入外部数据,或者从系统Buffer中读取从外部系统中读取的数据.如下图所示: 用户空间也就是我们自己的java程序有一个Buffer,系统

  • 浅谈Java并发中ReentrantLock锁应该怎么用

    目录 1.重入锁 说明 2.中断响应 说明 3.锁申请等待限时 tryLock(long, TimeUnit) tryLock() 4.公平锁 说明 源码(JDK8) 重入锁可以替代关键字 synchronized . 在 JDK5.0 的早期版本中,重入锁的性能远远优于关键字 synchronized , 但从 JDK6.0 开始, JDK 在关键字 synchronized 上做了大量的优化,使得两者的性能差距并不大. 重入锁使用 ReentrantLock 实现 1.重入锁 package

  • 浅谈java常用的几种线程池比较

    1. 为什么使用线程池 诸如 Web 服务器.数据库服务器.文件服务器或邮件服务器之类的许多服务器应用程序都面向处理来自某些远程来源的大量短小的任务.请求以某种方式到达服务器,这种方式可能是通过网络协议(例如 HTTP.FTP 或 POP).通过 JMS 队列或者可能通过轮询数据库.不管请求如何到达,服务器应用程序中经常出现的情况是:单个任务处理的时间很短而请求的数目却是巨大的. 构建服务器应用程序的一个简单模型是:每当一个请求到达就创建一个新线程,然后在新线程中为请求服务.实际上对于原型开发这

  • 浅谈Java回收对象的标记和对象的二次标记过程

    一.对象的标记 1.什么是标记?怎么标记? 第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的清理. 至于怎么标记,一般有两种方法:引用计数和可达性分析. 引用计数实现起来比较简单,就是给对象添加一个引用计数器,每当有一个地方引用它时就加1,引用失效时就减1,当计数器为0的时候就标记为可回收.这种判断效率很高,但是很多主流的虚拟机并没有采用这种方法,主要是因为它很难解决几个对象之间循环引用的问题,虽然不怎么用了,但还是值得我们学习! public class Test

随机推荐