Java 响应式编程理念篇:Reactive Streams 的设计初衷与核心原则
哥几个别用了ai就放弃学习底层原理了,AI写的代码看的懂吗?
在进行大模型接口调用时,大家应该经常见到Flux,Stream这些关键字吧?例如你通过langchain4j定义了一个StreamingChatModel,并通过AiServices构建一个接口让他返回Flux<T> ,你会发现这个Flux可以直接返回给前端进行流式响应,感觉非常好用。直到有一天你想调用国内的大模型发现不兼容langchain4j框架,只能引入对应大模型的sdk,而这个sdk又没有办法直接返回的Flux<T>这个时候,就要求你具有一定的响应式编程基础,并能将sdk的返回封装成Flux,以保证前端接受数据格式的统一性。例如:在传统的阻塞式调用中,线程会因为I/O调用而阻塞,他会一直处于等待并检查数据有没有返回,这样就造成了CPU资源的浪费。而在响应式编程中,全链路都是异步非阻塞,并且可以最大程度的利用CPU的多核性能。明白了要解决的问题,这个时候我们再来看响应式编程的核心理念就很清晰了:1.及时响应:通过全链路非阻塞实现,并最大化资源利用2.回弹性(指故障恢复能力):通过控制错误的传播范围来提供系统的健壮性3.弹性:这一点由背压机制实现,订阅者可以主动进行消费速率调节,防止订阅者被海量信息打爆4.消息驱动:响应式系统的基本特征,整个系统就是为了处理数据流而存在,这也点明了响应式编程的应用场景非阻塞:具体实现方法就是通过钩子函数来让上下游解耦,接收者(订阅者)不需要通过轮询来检查数据,而是通过被动接收通知的方式获知数据就绪,所以非阻塞可以节约大量的系统资源。背压:背压这个概念是相对于正压的,我们先说什么是正压,正压就是收到多少请求就开多少线程(或者占用对应的资源),如果资源不够了怎么办?那就排队、缓存,在这种情况下,你是很难控制资源的使用率的。所以背压这种理念就应运而生了,背压就是指消费端可以控制上游的数据发送速度。以此来动态精确控制资源使用率。消费端能主动控制速率就叫背压。在粗略了解了响应式基本理念后,大家应该能在第一时间想到:这不是就是目前我们和大模型的交互方式吗?大模型通过流式输出,一段一段的把数据输出到前端,用户无需等待全部数据加载完成。这即保证了用户不会因为长时间的等待而耗光耐心,也给了后端处理数据的时间。