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

posted on 2022-12-12 08:16  colorfulworld  阅读(437)  评论(0编辑  收藏  举报