如何在Spring MVC的contextConfigLocation中设置MongoDB ReadPreference

问题描述 投票:0回答:9

我正在 Spring MVC 中通过 mongodb java 驱动程序连接到 MongoDB 分片服务器。我正在使用以下版本:

  • spring-webmvc-3.2.1.RELEASE
  • mongo-java-driver/2.10.0/mongo-java-driver-2.10.0
  • spring-data-mongodb-1.2.0.RELEASE

我的 Mongo 选项在 contextConfigLocation 文件 mvc-dispatcher-servlet.xml 中设置

<mongo:mongo host="mongo.sample.com" port="30000">
     <mongo:options auto-connect-retry="true"
                    slave-ok="true"/>
</mongo:mongo>

它工作得很好,但 come.MongoDB.ReadPreference 已弃用从属 ok。 我只是想知道是否有任何方法可以在 contextConfiLocation 文件中设置 Spring MVC 的 readPreference 。

java mongodb spring-mvc sharding
9个回答
9
投票

声明以下 bean

<bean id="readPreferenceSecondary" class="com.mongodb.TaggableReadPreference.SecondaryReadPreference">
</bean>

你将其注入到你的 mongotemplate 中

<bean id="mongoTemplateProdDb" class="org.springframework.data.mongodb.core.MongoTemplate" >
        <property name="readPreference" ref="readPreferenceSecondary"></property>
</bean>

8
投票

通过将

ReadPreference
设置为
SECONDARY
,将@Trisha 的回复扩展为答案:“以编程方式在 MongoTemplate 中执行”。

MongoTemplate template = new MongoTemplate(...);
template.setReadPreference(com.mongodb.ReadPreference.SECONDARY);

4
投票

如果您使用 spring-data-mongodb 并且需要基于查找查询使用多个读取首选项,您可以创建多个 Mongo 模板和/或存储库,例如

    @EnableMongoRepositories(basePackages = {
            "com.you.repo.package" }, mongoTemplateRef = "mongoTemplateOne")    
    @Configuration
    public class MongoConfig {

    @Bean(name="mongoTemplateOne")
    public MongoTemplate getMongoTemplateOne() throws UnknownHostException {
        MongoTemplate templateOne = new MongoTemplate(new SimpleMongoDbFactory(new MongoClientURI("YOUR_MONGO_URL")));
        templateOne.setReadPreference(ReadPreference.secondaryPreferred());

        //setting WriteConcern but not relevant for this thread
        templateOne.setWriteConcernResolver(yourWriteConcernResolver());
        return templateOne;
    }

    @Bean(name = "mongoTemplateTwo")
    public MongoTemplate getMongoTemplateTwo() throws UnknownHostException {
        MongoTemplate templateTwo = new MongoTemplate(new SimpleMongoDbFactory(new MongoClientURI("YOUR_MONGO_URL")));
        templateTwo.setReadPreference(ReadPreference.secondaryPreferred());
        return templateTwo;
    }


    private WriteConcernResolver yourWriteConcernResolver() {
        return action -> {
            if (action.getCollectionName()
                    .equals("your_collecton")
                    && (action.getMongoActionOperation() == MongoActionOperation.SAVE
                            || action.getMongoActionOperation() == MongoActionOperation.UPDATE)) {
                return WriteConcern.MAJORITY;
            }
            return action.getDefaultWriteConcern();
        };
    }

2
投票

如果您有多个辅助节点(副本集),您可以使用 tags 更具体地告诉 mongo 驱动程序您想要从哪个辅助节点读取。

在 mongo 端运行以下命令:

db.getMongo().setReadPref('secondaryPreferred',
                          [{"tagName":"TagVal1"},
                            {"tagName":"TagVal2"},
                            {}])

在代码中它看起来像这样:

MongoTemplate template = new MongoTemplate(...)
template.setReadPreference(ReadPreference.secondaryPreferred("your DBObject that reflect your mongo tag names");

希望有帮助。


2
投票

这是使用 Mongo 存储库执行此操作的另一种方法

@Configuration
@EnableMongoRepositories
class ApplicationConfig extends AbstractMongoClientConfiguration {

    @Autowired
    private Environment env;

    @Value("${spring.data.mongodb.uri}")
    public String mongoUri;


    @Override
    protected String getDatabaseName() {
        return env.getProperty("spring.data.mongodb.database");
    }

    @Override
    protected void configureClientSettings(MongoClientSettings.Builder builder) {
        builder.applyConnectionString(new ConnectionString(mongoUri)).readPreference(ReadPreference.secondary());
    }

}

示例应用程序可用@ https://github.com/prashanthmadi/cosmosdb-mongodb-readpreference-springboot-java/blob/main/src/main/java/azure/cosmosdb/mongodb/spring/cosmosdbmongodb/ApplicationConfig.java


0
投票

如果需要根据集合混合主次读取,可以在

ReadPreference
对象上设置
DBCollection
。这有助于避免复杂的多个
MongoTemplate
配置。相反,在应用程序生命周期中设置一次集合级别首选项,如下所示。 该特定集合的所有读取都将转到辅助集合,而对于其他集合,它将转到主要集合。

DBCollection dbCollection = mongoTemplate.getCollection(mongoTemplate.getCollectionName(collection));
dbCollection.setReadPreference(ReadPreference.secondaryPreferred());

如果你想了解不同的实现方案,请查看Spring data mongodb二次读取


0
投票

spring-mongo-2.0.xsd 开始,

slave-ok
已被完全删除,但添加了对
ReadPreference
的 XML 配置的支持。以下是针对当前 XSD 翻译的原始问题的 XML:

<mongo:mongo-client host="mongo.sample.com" port="30000">
     <mongo:client-options read-preference="SECONDARY_PREFERRED" />
</mongo:mongo-client>

0
投票

或者您可以在存储库接口中使用注释在查询级别进行定义:

@Meta(flags = CursorOption.SECONDARY_READS)
Stream<MyClass> findBySomeField(String someField);

当使用 spring 从方法名称或注释(如 @Query@Aggregation

)生成查询时,这非常有用

0
投票

如果您使用 SpringBoot 的“MongoRepository”接口,您只需将 @ReadPreference("secondaryPreferred") 添加到该方法即可。

public interface MyRepository extends MongoRepository<MyItem, String>
{
    @ReadPreference("secondaryPreferred")
    public Optional<MyItem> findById(String id);
© www.soinside.com 2019 - 2024. All rights reserved.