反应式服务中的线程本地状态可用性

任何体系结构决策都需要权衡。 如果您决定采用反应式,也没有什么不同,例如,一方面使用反应式流实现几乎可以立即获得更好的资源利用率,但另一方面会使调试更加困难。 引入反应式库也对您的域产生巨大影响,您的域将不再仅在PaymentOrderCustomer方面说话,反应式术语将破解Flux<Payment>Flux<Order>Mono<Customer> (或Observable<Payment>Flowable<Order>Single<Customer>或您选择的库提供的任何Reactive Streams发布者)。 这种折衷很快就变得很明显,但是您可能会猜想并非所有的折衷都会如此明显– 泄漏抽象定律保证了这一点。

反应性库使更改线程上下文变得轻而易举。 您可以轻松地订阅一个调度程序,然后在另一个调度程序上执行一部分操作员链,最后跳到完全不同的调度程序上。 只要不涉及线程局部状态,这种从一个线程到另一个线程的跳转就可以工作-尽管它支持服务的关键部分(例如安全性,事务),但通常不会每天处理该状态, 多租户)。 当您的技术堆栈中隐藏良好的部分取决于线程局部状态时,更改线程上下文会导致棘手的错误定位。

让我通过一个简单的示例演示该问题:

private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static final String SESSION_ID = "session-id";@GetMapping("documents/{id}")
Mono<String> getDocument(@PathVariable("id") String documentId) {MDC.put(SESSION_ID, UUID.randomUUID().toString());LOG.info("Requested document[id={}]", documentId);return Mono.just("Lorem ipsum").map(doc -> {LOG.debug("Sanitizing document[id={}]", documentId);return doc.trim();});
}

使用MDC.put(SESSION_ID, UUID.randomUUID().toString())我们将会话session-id放入基础日志库的映射诊断上下文中 ,以便稍后进行登录。

让我们以自动为我们记录session-id的方式配置记录模式:

logging.pattern.console=[%-28thread] [%-36mdc{session-id}] - %-5level - %msg%n

当我们通过请求( curl localhost:8080/documents/42 )访问公开的服务时,我们将看到session-id出现在日志条目中:

[reactor-http-server-epoll-10] [00c4b05f-a6ee-4a7d-9f92-d9d53dbbb9d0] - INFO  - Requested document[id=42]
[reactor-http-server-epoll-10] [00c4b05f-a6ee-4a7d-9f92-d9d53dbbb9d0] - DEBUG - Sanitizing document[id=42]

如果在将session-id放入MDC之后切换执行上下文(例如,通过预订不同的调度程序),情况将发生变化:

@GetMapping("documents/{id}")
Mono<String> getDocument(@PathVariable("id") String documentId) {MDC.put(SESSION_ID, UUID.randomUUID().toString());LOG.info("Requested document[id={}]", documentId);return Mono.just("Lorem ipsum").map(doc -> {LOG.debug("Sanitizing document[id={}]", documentId);return doc.trim();}).subscribeOn(Schedulers.elastic()); // don't use schedulers with unbounded thread pool in production
}

执行上下文更改后,我们将注意到该调度程序调度的操作员记录的日志条目中缺少session-id

[reactor-http-server-epoll-10] [c2ceae03-593e-4fb3-bbfa-bc4970322e44] - INFO  - Requested document[id=42]
[elastic-2                   ] [                                    ] - DEBUG - Sanitizing document[id=42]

您可能会猜到,我们正在使用的日志记录库内部深处隐藏着一些ThreadLocal

一些Reactive Streams实现提供了允许将上下文数据提供给操作员的机制(例如Project Reactor提供订户上下文 ):

@GetMapping("documents/{id}")
Mono<String> getDocument4(@PathVariable("id") String documentId) {String sessionId = UUID.randomUUID().toString();MDC.put(SESSION_ID, sessionId);LOG.info("Requested document[id={}]", documentId);return Mono.just("Lorem ipsum").zipWith(Mono.subscriberContext()).map(docAndCtxTuple -> {try(MDC.MDCCloseable mdc = MDC.putCloseable(SESSION_ID, docAndCtxTuple.getT2().get(SESSION_ID))) {LOG.debug("Sanitizing document[id={}]", documentId);return docAndCtxTuple.getT1().trim();}}).subscriberContext(Context.of(SESSION_ID, sessionId)).subscribeOn(Schedulers.elastic()); // don't use schedulers with unbounded thread pool in production
}

当然,使数据可用只是故事的一部分。 一旦我们提供了session-idsubscriberContext(Context.of(SESSION_ID, sessionId)) ),我们不仅必须检索它,还必须将其附加到线程上下文中,并且由于调度程序可以自由地记住自己,所以请自己清理一下。重用线程。

提出的实现会带回session-id

[reactor-http-server-epoll-10] [24351524-f105-4746-8e06-b165036d02e6] - INFO  - Requested document[id=42]
[elastic-2                   ] [24351524-f105-4746-8e06-b165036d02e6] - DEBUG - Sanitizing document[id=42]

但是,使它起作用的代码太复杂,太具有侵入性,以致于在大多数代码库中都不会张开双臂来欢迎它,尤其是当它最终散布在整个代码库中时。

我很乐意通过为该问题提供一个简单的解决方案来结束本博文,但我尚未偶然发现这样的问题(现在,我们需要使用这样更复杂,更具侵入性的解决方案,同时还要尝试解决这种复杂性从以业务为中心的软件部分到基础设施部分,如果可能,还可以直接到库本身)。

翻译自: https://www.javacodegeeks.com/2018/09/thread-local-state-availability-in-reactive-services.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/345248.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【渝粤题库】陕西师范大学100101美学概论作业(高起本)

《美学概论》作业 一、写出下列美学著作的作者 1.《文艺对话集》 2.《Aesthetik》 3.《论语》 4.《文心雕龙》 5.《人间词话》 6.《美的历程》 7.《生活与美学》 8.《1844年经济学—哲学手稿》 9.《审美教育书简》 10.《判断力批判》 11.美是主客观的统一 12.美在和谐 13.美是…

【渝粤题库】陕西师范大学151205 财务管理原理作业(笔试题型)

《财务管理原理&#xff08;专升本&#xff09;》作业 一、单项选择题 1、融资租赁又称财务租赁&#xff0c;有时也称资本租赁。下列&#xff08; &#xff09;情形不属于融资租赁范围。 A、根据协议&#xff0c;企业将某项资产卖给出租人&#xff0c;再将其租回使用 B、由租赁…

自定义条件查询_数据查询不止有vlookup函数,自定义zlookup函数查询操作更高效...

Excel数据查询&#xff0c;相信大家首先会想到vlookup函数。毋庸置疑vlookup函数在Excel数据查询中作用是非常的强大。但是它也有一些不能实现的数据查询。如上图所示&#xff0c;我们需要根据人员的出现次数&#xff0c;提取第N次的数据。这里vlookup函数就无法使用&#xff0…

2021年中国工业互联网行业发展现状分析,“5G+工业互联网”驱动行业快速发展

一、概述 工业互联网是新一代信息通信技术与工业经济深度融合的新型基础设施、应用模式和工业生态&#xff0c;通过对人、机、物、系统等的全面连接&#xff0c;构建起覆盖全产业链、全价值链的全新制造和服务体系&#xff0c;为工业乃至产业数字化、网络化、智能化发展提供了…

【渝粤题库】陕西师范大学152212 政府绩效管理 作业(专升本)

陕西师范大学 内 部 题 库 教育 &#xff08;yuyueshool&#xff09; 编制 陕西师范大学 内 部 题 库 教育 &#xff08;yuyueshool&#xff09; 编制 《政府绩效管理》作业 一、单选题 1.&#xff08; &#xff09;是指公共服务部门将公共服务的内容、标准、程序和责任等公…

针对数能同传SWIPT的个人理解与总结Part1

无线数能同传&#xff08;Simultaneous Wireless Information and Power Transfer, SWIPT&#xff09;技术是指利用无线射频信号可同时携载信息与能量的特点&#xff0c;从一个射频信号中同时接收信息与能量的技术。 一、接收机架构 SWIPT有很多种解释&#xff0c;携能通信、…

【渝粤题库】陕西师范大学164111 Java及JSP动态网页编程与应用 作业 (高起专)

《JAVA与JSP动态网页编程与应用》作业 一、单选题 1.以下哪项都是关键字&#xff08; &#xff09; A&#xff0e;package privati protect throw B. false final finally float C. this threadsafe super thread D. abstract bool break main 2.以下哪种循环体能保证进入执行&…

米筐量化不支持c语言_量化 | 从零开始学量化(三):数据获取途径

本系列的前两篇都是一些笼统的介绍&#xff0c;供小白制定学习计划时参考&#xff0c;现在该铺垫的都铺垫的差不多了。循序渐进&#xff0c;从本篇开始会写一些能实操的内容&#xff0c;尽量写的很细节&#xff0c;有任何问题欢迎私戳。本篇给出一些数据获取途径&#xff0c;基…

jvm破坏双亲委派_破坏JVM

jvm破坏双亲委派正如我们最近发现的那样&#xff0c;全面测试可能有害。 扩展测试覆盖范围导致我们仅花费一行代码就进行了几个小时的调试会话。 使调试特别令人不愉快的是&#xff0c;该代码不仅崩溃了所部署的JVM&#xff0c;而且还破坏了其下的虚拟机和/或物理机。 因此&am…

【渝粤题库】陕西师范大学165204 市场调查与分析方法 作业(专升本)

《市场调查与分析方法》作业 一、单选题 1、“某个行业的历史销售趋势是什么样的&#xff1f;”属于市场调查功能中的&#xff08; &#xff09; A、描述 B、诊断 C、预测 D、重构 2、利用企业内部和外部现有的各种信息、情报资料&#xff0c;对调查内容进行分析研究的调查方法…

射频知识简介

无线通信系统中&#xff0c;一般包含有天线、射频前端、射频收发模块以及基带信号处理器四个部分。随着5G时代的&#xff0c;天线以及射频前端的需求量及价值均快速上升&#xff0c;射频前端是将数字信号向无线射频信号转化的基础部件&#xff0c;也是无线通信系统的核心组件。…

【渝粤题库】陕西师范大学200341实变函数作业(高起本、专升本)

《实变函数》作业 一&#xff0e;判断题 1&#xff0e; 可测的充要条件是可测。 &#xff08; &#xff09; 2&#xff0e;所有无理数构成的集合是可数集。 &#xff08; &#xff09; 3&#xff0e;如果在上单调减少&#xff0c;则在上可测。 &#xff08; &#xff09; 4&…

尽可能地做到无服务器,但不止于此

毫无疑问&#xff0c;如果您一直关注技术趋势&#xff0c;那么您会看到“无服务器”的兴起。 在某些情况下&#xff0c;“无服务器”被称为“下一个应用程序体系结构”样式。 我什至听说有人说“您不需要技术X&#xff0c;因为无服务器是未来的方式”或“技术X是红鲱鱼&#xf…

信号扫描_科研必备“武器”之扫描电子显微镜

仪器介绍扫描电子显微镜&#xff08;英语名称为Scanning Electron Microscope&#xff0c;缩写为SEM&#xff09;&#xff0c;简称扫描电镜。它是一种电子显微镜&#xff0c;利用聚焦电子束扫描样品的表面来产生样品表面的图像。最常见的扫描电镜模式是检测由电子束激发的原子发…

【渝粤题库】陕西师范大学200711 面向对象方法与C++ 作业

《面向对象方法与C》作业 一、填空题 1&#xff0e;若char *string”test”;则如果要输出指针值&#xff0c;正确的语句是 。 2&#xff0e;在重载“[ ]”运算符时&#xff0c;必须使用 函数重载。 3&#xff0e;当用public继承时&#xff0c;基类的public成员成为派生类的 成员…

解决office一打开就显示正在更新,过一会就报错的问题

问题描述&#xff1a; 一打开office就显示正在更新&#xff0c;请稍后&#xff0c;过一会就弹窗报错。 解决方案&#xff1a; 1.winR输入services.msc 2.将Microsoft Office即点即用服务设为自动 如果第二步中已经是自动状态&#xff0c;先禁用一下&#xff0c;再重新设置为…

【渝粤题库】陕西师范大学201281 民法作业

《民法学》作业 一、单项选择题 1&#xff0e;诉讼时效作为权利人不行使权利就丧失人民法院保护其民事权利的法定期间&#xff0c;它一般适用于&#xff1f; A&#xff0e;支配权    B&#xff0e;请求权    C&#xff0e;形成权    D&#xff0e;抗辨权 2&#xff0e;民…

框架如何调用存储过程_如何在FastReport.Net中使用存储过程

在本文中&#xff0c;我们将讨论使用存储过程来检索报表的数据&#xff0c;使用MS SQL示例&#xff0c;将展示如何在报表中创建和使用函数。Transact SQL允许创建存储过程和函数&#xff0c;存储过程用于自动执行任何操作&#xff0c;这些功能旨在扩展查询功能&#xff0c;它们…

【渝粤题库】陕西师范大学201731教育测量与评价 作业 (专升本、高起本、高起专)

《教育测量与评价》作业 一、名词解释 教育评价常模参照解释标准分教育测量集中量数效度区分度绝对评价 二、填空题测量的要素有_____, 和_。命题蓝图一般包括________、 ________ 、________、 ________ 和_______等内容。近代教育测量发展史上有重要影响的两件事是_______ 和…

Word无法插入公式项目灰色不可用

在我们平时办公或者是论文写作过程中&#xff0c;插入编辑公式是非常常见的操作。但是有时候我们打开Word点击插入发现公式图标为灰色且不可选。接下来我将介绍如何解决。 1、打开文档找到插入公式位置点击插入选项。 2、发现公式符号变为灰色且不可选择。 3、点击左上角的【文…