reactive编程是一种异步编程的方案。
代码编写风格:命令式和反应式
命令式: springmvc可以理解为命令式编程,程序由不同function组成,程序运行时顺序执行对应function,下边的function依赖上边function,在上一个function还没有完成时不能将数据传给下一个function
WebMvc 阻塞式模型,请求到达后,分配一个线程去处理,如果程序中涉及IO(调用其他接口,db查询等),在IO操作结束后一直处于阻塞等待状态,这样在等待IO操作结束时间就被浪费
反应式: spring WebFlux可以理解成反应式编程,程序由不同function组成,但这些function可以并行执行,这种异步非阻塞执行可以提高代码执行效率,但值得注意是由于function并行执行,上一个function的执行结果不能作为下一个function的入参,因为下一个fucntion在调用上一个function 结果时,上边function不一定执行结束(甚至还没开始执行)。
反应式编程的核心是基于事件流、无阻塞、异步的。使用反应式编程不需要编写底层的并发代码
WebFlux 异步非阻塞模型,内部使用响应式编程,提高系统吞吐量。springwebflux它并不能提高接口响应时间,但可以在高并发情况下提高吞吐量
反应是编程基本概念
Flux和Mono都是数据流的发布者
Flux:用于返回多个元素操作
Mono:用于返回单个元素操作
Spring WebFlux
spring webFlux是面向Spring的反应式Web框架
Reactive Mongo
reactive mongo是一种异步非阻塞,面向流开发方式
以下例子中展示采用mongoTemplate vs reactive mongoTemplate访问数据区别
public abstract class AbstractMongoConfig { public MongoDatabaseFactory mongoDatabaseFactory(String uri, String database) throws Exception { ConnectionString connectionString = new ConnectionString(uri); return new SimpleMongoClientDatabaseFactory(MongoClients.create(connectionString), database); } public abstract MongoTemplate getMongoTemplate() throws Exception; } //mongoTemplate @Configuration // @EnableMongoRepositories("com.citi.xip.market.data.repository") @Data @Immutable @EqualsAndHashCode(callSuper = false) @Slf4j public class MongoConfig extends AbstractMongoConfig { @Value("${spring.data.mongodb.database}") private String database; @Value("${spring.data.mongodb.uri}") private String uri; @Autowired private CyberarkUtil cyberarkUtil; @Primary @Override @Bean(name = "mongoTemplate") public MongoTemplate getMongoTemplate() throws Exception { String newUri = uri.replace("password", cyberarkUtil.retrievePassword()); return new MongoTemplate(mongoDatabaseFactory(newUri, database)); } public boolean pingPrimaryMongo(MongoTemplate mongoTemplate) { try { mongoTemplate.find(new Query(), Map.class); log.info("ping mongo success"); return true; } catch (Exception e) { log.error("ping mongo with error: ", e); return false; } } @Bean public GridFsTemplate gridFsTemplate(MappingMongoConverter mappingMongoConverter) throws Exception { String newUri = uri.replace("password", cyberarkUtil.retrievePassword()); return new GridFsTemplate(mongoDatabaseFactory(newUri, database), mappingMongoConverter); } } //Reactive mongoTemplate @Configuration @EnableReactiveMongoRepositories @Slf4j public class ReactiveMongoConfig extends AbstractReactiveMongoConfiguration { @Autowired CyberarkUtil cyberarkUtil; @Autowired private Environment environment; @Autowired private ObjectProvider<List<MongoClientSettingsBuilderCustomizer>> builderCustomizers; @Value("${spring.data.mongodb.database}") private String database; @Value("${spring.data.mongodb.uri}") private String uri; private MongoClient mongoClient; @Override public MongoClient reactiveMongoClient() { String newUri = uri.replace("password", cyberarkUtil.retrievePassword()); ConnectionString connectionString = new ConnectionString(newUri); MongoClientSettings mongoClientSettings = MongoClientSettings.builder().applyConnectionString(connectionString).build(); return MongoClients.create(mongoClientSettings); } @Primary @Bean public ReactiveMongoTemplate getReactiveMongoTemplate() { if (mongoClient != null) { mongoClient.close(); mongoClient = null; } ReactiveMongoDatabaseFactory mongoDbFactory = new SimpleReactiveMongoDatabaseFactory(reactiveMongoClient(), database); return new ReactiveMongoTemplate(mongoDbFactory); } public Mono<Boolean> pingMongo(ReactiveMongoTemplate mongoTemplate) { return mongoTemplate.find(new Query(), Map.class).hasElements().onErrorReturn(Boolean.FALSE); } @Override protected String getDatabaseName() { return database; } } //service @Service public class mongoProcessService { public Flux<Map> findReactive(){ Query query = new Query(); Flux<Map> mapFlux= reactiveMongoTemplate.find(query, Map.class, "table2"); return mapFlux; } public List<Map> findDirectly(){ Query query = new Query(); List<Map> result= mongoTemplate.find(query, Map.class, "table2"); return result; } }
当table2中数据两很大时,采用reactivemongotemplate查询会流式返回数据;但如果采用mongotemplate查询由于table2 数据量太大,会直接oom,页面报错显示如下:
ReactivemongoTemplate是异步非阻塞 流式返回,并不是等所有查询数据准备好之后一齐返回;而mongotemplate是同步阻塞式返回,当所有数据查完之前会一直处于阻塞状态,当所有数据查询结束后一齐返回,这样会增大内存使用率以及用户体验
参考:
https://blog.51cto.com/u_15236724/5686682
https://blog.csdn.net/zhang33565417/article/details/122012459?spm=1001.2101.3001.6650.7&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-7-122012459-blog-122708419.pc_relevant_3mothn_strategy_recovery&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-7-122012459-blog-122708419.pc_relevant_3mothn_strategy_recovery&utm_relevant_index=11
https://www.jb51.net/article/274139.htm
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?