首页 > 解决方案 > 使用最新的 Spring Data Mongo 反应时的 Mongo 转换异常

问题描述

当我尝试使用 Mongo 4 和最新的 Spring Data Mongo Reactive 的事务功能时,我遇到了这样的失败。

18:57:22.823 [main] ERROR org.mongodb.driver.client - Callback onResult call produced an error
reactor.core.Exceptions$ErrorCallbackNotImplemented: com.mongodb.MongoClientException: Sessions are not supported by the MongoDB cluster to which this client is connected
Caused by: com.mongodb.MongoClientException: Sessions are not supported by the MongoDB cluster to which this client is connected
    at com.mongodb.async.client.MongoClientImpl$1.onResult(MongoClientImpl.java:90)
    at com.mongodb.async.client.MongoClientImpl$1.onResult(MongoClientImpl.java:83)
    at com.mongodb.async.client.ClientSessionHelper$2.onResult(ClientSessionHelper.java:80)
    at com.mongodb.async.client.ClientSessionHelper$2.onResult(ClientSessionHelper.java:73)
    at com.mongodb.internal.connection.BaseCluster$ServerSelectionRequest.onResult(BaseCluster.java:433)
    at com.mongodb.internal.connection.BaseCluster.handleServerSelectionRequest(BaseCluster.java:297)
    at com.mongodb.internal.connection.BaseCluster.selectServerAsync(BaseCluster.java:157)
    at com.mongodb.internal.connection.SingleServerCluster.selectServerAsync(SingleServerCluster.java:41)
    at com.mongodb.async.client.ClientSessionHelper.createClientSession(ClientSessionHelper.java:68)
    at com.mongodb.async.client.MongoClientImpl.startSession(MongoClientImpl.java:83)
    at com.mongodb.reactivestreams.client.internal.MongoClientImpl$1.apply(MongoClientImpl.java:153)
    at com.mongodb.reactivestreams.client.internal.MongoClientImpl$1.apply(MongoClientImpl.java:150)
    at com.mongodb.async.client.SingleResultCallbackSubscription.requestInitialData(SingleResultCallbackSubscription.java:38)
    at com.mongodb.async.client.AbstractSubscription.tryRequestInitialData(AbstractSubscription.java:153)
    at com.mongodb.async.client.AbstractSubscription.request(AbstractSubscription.java:84)
    at com.mongodb.reactivestreams.client.internal.ObservableToPublisher$1$1.request(ObservableToPublisher.java:50)
    at reactor.core.publisher.MonoNext$NextSubscriber.request(MonoNext.java:102)
    at reactor.core.publisher.MonoProcessor.onSubscribe(MonoProcessor.java:399)
    at reactor.core.publisher.MonoNext$NextSubscriber.onSubscribe(MonoNext.java:64)
    at com.mongodb.reactivestreams.client.internal.ObservableToPublisher$1.onSubscribe(ObservableToPublisher.java:39)
    at com.mongodb.async.client.SingleResultCallbackSubscription.<init>(SingleResultCallbackSubscription.java:33)
    at com.mongodb.async.client.Observables$2.subscribe(Observables.java:76)
    at com.mongodb.reactivestreams.client.internal.ObservableToPublisher.subscribe(ObservableToPublisher.java:36)
    at reactor.core.publisher.MonoFromPublisher.subscribe(MonoFromPublisher.java:43)
    at reactor.core.publisher.Mono.subscribe(Mono.java:3555)
    at reactor.core.publisher.MonoProcessor.add(MonoProcessor.java:531)
    at reactor.core.publisher.MonoProcessor.subscribe(MonoProcessor.java:444)
    at reactor.core.publisher.MonoFlatMapMany.subscribe(MonoFlatMapMany.java:49)
    at reactor.core.publisher.Flux.subscribe(Flux.java:7677)
    at reactor.core.publisher.Flux.subscribeWith(Flux.java:7841)
    at reactor.core.publisher.Flux.subscribe(Flux.java:7670)
    at reactor.core.publisher.Flux.subscribe(Flux.java:7634)
    at com.example.demo.DataInitializer.init(DataInitializer.java:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:261)
    at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:180)
    at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:142)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:398)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:355)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:884)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
    at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:88)
    at com.example.demo.Application.main(Application.java:24)

我使用了一个初始化类来初始化这个类。

@Component
@Slf4j
class DataInitializer {

    private final ReactiveMongoOperations mongoTemplate;

    public DataInitializer(ReactiveMongoOperations mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    @EventListener(value = ContextRefreshedEvent.class)
    public void init() {
        log.info("start data initialization  ...");
        this.mongoTemplate.inTransaction()
            .execute(
                s ->
                    Flux
                        .just("Post one", "Post two")
                        .flatMap(
                            title -> s.insert(Post.builder().title(title).content("content of " + title).build())
                        )

            )
            .subscribe(
                null,
                null,
                () -> log.info("done data initialization...")
            );
    }

}

订阅导致此异常。

源代码推送到我的github 。

我只是用新的mongoTemplate.inTransaction()替换 DataInitializer 的内容。

PS:我在Docker容器中使用了最新的Mongo来服务mongodb服务,目前是4.0.1。Docker 控制台显示:

mongodb_1    | 2018-08-20T15:56:04.434+0000 I CONTROL  [main] Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols 'none'
mongodb_1    | 2018-08-20T15:56:04.447+0000 I CONTROL  [initandlisten] MongoDB starting : pid=1 port=27017 dbpath=/data/db 64-bit host=12635c1c3d2d
mongodb_1    | 2018-08-20T15:56:04.447+0000 I CONTROL  [initandlisten] db version v4.0.1
mongodb_1    | 2018-08-20T15:56:04.448+0000 I CONTROL  [initandlisten] git version: 54f1582fc6eb01de4d4c42f26fc133e623f065fb

更新:当我尝试通过Docker Compose 文件将 Mongo 服务器作为副本集启动时:

version: "3"
services:
  mongo1:
    hostname: mongo1
    container_name: localmongo1
    image: mongo:4.0-xenial
    ports:
      - "27017:27017"
    restart: always
    entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "rs0" ]
  mongo2:
    hostname: mongo2
    container_name: localmongo2
    image: mongo:4.0-xenial
    ports:
      - "27018:27017"
    restart: always
    entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "rs0" ]
  mongo3:
    hostname: mongo3
    container_name: localmongo3
    image: mongo:4.0-xenial
    ports:
      - "27019:27017"
    restart: always
    entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "rs0" ]

并将 Mongo uri 字符串更改为:

mongodb://localhost:27017,localhost:27018,localhost:27019/blog

然后得到失败信息,如:

11:08:20.845 [main] INFO org.mongodb.driver.cluster - No server chosen by com.mongodb.async.client.ClientSessionHelper$1@796d3c9f from cluster description ClusterDescription{type=UNKNOWN, 

标签: spring-data-mongodbspring-webfluxproject-reactor

解决方案


推荐阅读