2017-10-19 51 views
4

我有一種情況,我有多個客戶端連接到我的應用程序,我想在同一個Mongo服務器中爲每個客戶端提供他們自己的「模式/數據庫」。如何使用Mongodb在spring-boot中使用多個dbs的單實例

我的配置類:

@Configuration 
public class MongoDbConfiguration { 

@Bean 
@Primary 
public MongoDbFactory mongoDbFactory() throws UnknownHostException { 
    return new MultiTenantMongoDbFactory(); 
} 

@Bean 
@Primary 
public MongoTemplate mongoTemplate() throws UnknownHostException { 
    return new MongoTemplate(mongoDbFactory()); 
} 
} 

多租戶Db的工廠

public class MultiTenantMongoDbFactory extends SimpleMongoDbFactory { 

public MultiTenantMongoDbFactory() throws UnknownHostException { 
    super(getMongoClient(), TenantContext.getTenant()); 
} 

@Override 
public DB getDb() throws DataAccessException { 
    String tenant = TenantContext.getTenant(); 
    return getDb(tenant); 

} 

private static MongoClient getMongoClient() { 
    String tenant = TenantContext.getTenant(); 
    System.out.println("Database name in factory class :"+tenant); 
    if (tenant.equalsIgnoreCase("ncet")) { 
     MongoCredential mongoCredential = MongoCredential.createCredential("user1", "db1", 
       "pwd1".toCharArray()); 
     ServerAddress serverAddress = new ServerAddress("localhost", 27017); 
     MongoClient mongoClient = new MongoClient(serverAddress, Arrays.asList(mongoCredential)); 
     return mongoClient; 
    }else{ 
     MongoCredential mongoCredential = MongoCredential.createCredential("user1", "db2", 
       "pwd2".toCharArray()); 
     ServerAddress serverAddress = new ServerAddress("localhost", 27017); 
     MongoClient mongoClient = new MongoClient(serverAddress, Arrays.asList(mongoCredential)); 
     return mongoClient; 
    } 

} 

每個數據庫都有憑據

+0

您的問題尚不清楚。這是身份驗證問題還是mongodb與多個dbs問題?你想配置一個副本集嗎?如果你有錯誤,你能否提供堆棧跟蹤? –

+0

我在我的應用程序中使用了spring-data mongo存儲庫和彈簧引導。對於需要配置多個數據庫的單個mongo實例。應用程序有多個客戶端,每個客戶端都有專用數據庫試圖做多tency –

+0

什麼是你得到的異常,在你的問題中發佈堆棧跟蹤 –

回答

2

您的示例不起作用,因爲getMongoClient()在啓動過程中僅調用一次,但您需要在運行時基於活動租戶更改它。以春季SimpleMongoDbFactory爲例,實現多租戶專用MongoDbFactory非常簡單。如果需要,您可以添加更多邏輯(對於writeConcern等)。 這個樣本中有兩個租戶(東部和西部)。每個租戶都有自己的MongoClient,並在MongoConfig中配置了相應的數據庫名稱和憑證。 TenantDataFactory根據當前TenantTenantContext返回租戶相關信息。使用MongoClientTenantDataTenantDataFactory返回的數據庫名稱創建DB對象。

public class MultiTenantMongoDbFactory implements MongoDbFactory { 

    private PersistenceExceptionTranslator exceptionTranslator; 
    private TenantDataFactory tenantDataFactory; 

    public MultiTenantMongoDbFactory(TenantDataFactory tenantDataFactory) { 
    this.exceptionTranslator = new MongoExceptionTranslator(); 
    this.tenantDataFactory = tenantDataFactory; 
    } 

    @Override 
    public DB getDb(String dbName) throws DataAccessException { 
    return getDb(); 
    } 

    @Override 
    public DB getDb() throws DataAccessException { 
    Tenant tenant = TenantContext.getCurrentTenant(); 
    TenantData tenantData = tenantDataFactory.getTenantData(tenant); 
    return MongoDbUtils.getDB(tenantData.getClient(), tenantData.getDbName()); 
    } 

    @Override 
    public PersistenceExceptionTranslator getExceptionTranslator() { 
    return exceptionTranslator; 
    } 
} 

public class TenantDataFactory { 

    private Map<Tenant, TenantData> tenantDataMap; 

    public TenantDataFactory(Map<Tenant, TenantData> tenantDataMap) { 
    this.tenantDataMap = Collections.unmodifiableMap(tenantDataMap); 
    } 

    public TenantData getTenantData(Tenant tenant) { 
    TenantData tenantData = tenantDataMap.get(tenant); 
    if (tenantData == null) { 
     // or return default tenant 
     throw new IllegalArgumentException("Unsupported tenant " + tenant); 
    } 
    return tenantData; 
    } 
} 

public enum Tenant { 
    EAST, WEST 
} 

public class TenantData { 

    private final String dbName; 
    private final MongoClient client; 

    public TenantData(String dbName, MongoClient client) { 
    this.dbName = dbName; 
    this.client = client; 
    } 

    public String getDbName() { 
    return dbName; 
    } 

    public MongoClient getClient() { 
    return client; 
    } 
} 

public class TenantContext { 

    private static ThreadLocal<Tenant> currentTenant = new ThreadLocal<>(); 

    public static void setCurrentTenant(Tenant tenant) { 
    currentTenant.set(tenant); 
    } 

    public static Tenant getCurrentTenant() { 
    return currentTenant.get(); 
    } 
} 

@Configuration 
public class MongoConfig { 

    @Bean(name = "eastMongoClient", destroyMethod = "close") 
    public MongoClient eastMongoClient() { 
    return new MongoClient(new ServerAddress("127.0.0.1", 27017), 
     Collections.singletonList(MongoCredential.createCredential("user1", "east", "password1".toCharArray()))); 
    } 

    @Bean(name = "westMongoClient", destroyMethod = "close") 
    public MongoClient westMongoClient() { 
    return new MongoClient(new ServerAddress("127.0.0.1", 27017), 
     Collections.singletonList(MongoCredential.createCredential("user2", "west", "password2".toCharArray()))); 
    } 

    @Bean 
    public TenantDataFactory tenantDataFactory(@Qualifier("eastMongoClient") MongoClient eastMongoClient, 
              @Qualifier("westMongoClient") MongoClient westMongoClient) { 
    Map<Tenant, TenantData> tenantDataMap = new HashMap<>(); 
    tenantDataMap.put(Tenant.EAST, new TenantData("east", eastMongoClient)); 
    tenantDataMap.put(Tenant.WEST, new TenantData("west", westMongoClient)); 
    return new TenantDataFactory(tenantDataMap); 
    } 

    @Bean 
    public MongoDbFactory mongoDbFactory(@Autowired TenantDataFactory tenantDataFactory) { 
    return new MultiTenantMongoDbFactory(tenantDataFactory); 
    } 

    @Bean 
    public MongoTemplate mongoTemplate(@Autowired MongoDbFactory mongoDbFactory) { 
    return new MongoTemplate(mongoDbFactory); 
    } 
} 
+0

每個實例具有憑證如何傳遞憑據。上面的方法如何發送憑據?請幫助我站在下面。 我解決了使用:https://[email protected]/atanvi/multitency.git不確定的方法... –

+0

有兩個單獨的'MongoClient'爲每個租戶有不同的主機和憑據在'MongoConfig'。 –

+0

每個房客應該只有一個MongoClient,我不知道該怎麼做 –

1

我解決了這個:

https://[email protected]/atanvi/multitency

和謝謝@Nikita Gorbachevski

+0

似乎這是私人存儲庫,所以我不能查看它。 –

+0

對不起,已更改存儲庫爲公共,請看看。謝謝 –

+0

只是對你的Git倉庫有一點建議:你不應該提交你的'bin /'目錄。 –

相關問題