spring 数据弹性搜索动态多租户索引不匹配?
spring data elasticsearch dynamic multi tenant index mismatch?
我正在通过实施一个集群来试验 spring 数据弹性搜索,该集群将托管多租户索引,每个租户一个索引。
我能够为每个需要的索引动态创建和设置设置,例如
public class SpringDataES {
@Autowired
private ElasticsearchTemplate es;
@Autowired
private TenantIndexNamingService tenantIndexNamingService;
private void createIndex(String indexName) {
Settings indexSettings = Settings.builder()
.put("number_of_shards", 1)
.build();
CreateIndexRequest indexRequest = new CreateIndexRequest(indexName, indexSettings);
es.getClient().admin().indices().create(indexRequest).actionGet();
es.refresh(indexName);
}
private void preapareIndex(String indexName){
if (!es.indexExists(indexName)) {
createIndex(indexName);
}
updateMappings(indexName);
}
模型是这样创建的
@Document(indexName = "#{tenantIndexNamingService.getIndexName()}", type = "movies")
public class Movie {
@Id
@JsonIgnore
private String id;
private String movieTitle;
@CompletionField(maxInputLength = 100)
private Completion movieTitleSuggest;
private String director;
private Date releaseDate;
其中索引名称是通过 SpEl 动态传递的
#{tenantIndexNamingService.getIndexName()}
服务于
@Service
public class TenantIndexNamingService {
private static final String INDEX_PREFIX = "test_index_";
private String indexName = INDEX_PREFIX;
public TenantIndexNamingService() {
}
public String getIndexName() {
return indexName;
}
public void setIndexName(int tenantId) {
this.indexName = INDEX_PREFIX + tenantId;
}
public void setIndexName(String indexName) {
this.indexName = indexName;
}
}
因此,每当我必须执行 CRUD 操作时,首先我指向正确的索引,然后执行所需的操作
tenantIndexNamingService.setIndexName(tenantId);
movieService.save(new Movie("Dead Poets Society", getCompletion("Dead Poets Society"), "Peter Weir", new Date()));
我的假设是以下动态索引分配在多线程 Web 应用程序中无法正常工作:
@Document(indexName = "#{tenantIndexNamingService.getIndexName()}"
这是因为 TenantIndexNamingService 是单例的。
所以我的问题是如何以线程保存方式实现正确的行为?
我可能会采用类似于以下为 Cassandra 提议的方法:
您可以在此处查看相关的 GitHub 存储库:
现在,由于 Elastic 在您定义文档的方式上有所不同,您应该主要关注定义一个请求范围的 bean,它将封装您的租户 ID 并将其绑定到您的传入请求。
这是我的解决方案。我创建了一个 RequestScope bean 来保存每个 HttpRequest
的索引
我正在通过实施一个集群来试验 spring 数据弹性搜索,该集群将托管多租户索引,每个租户一个索引。
我能够为每个需要的索引动态创建和设置设置,例如
public class SpringDataES {
@Autowired
private ElasticsearchTemplate es;
@Autowired
private TenantIndexNamingService tenantIndexNamingService;
private void createIndex(String indexName) {
Settings indexSettings = Settings.builder()
.put("number_of_shards", 1)
.build();
CreateIndexRequest indexRequest = new CreateIndexRequest(indexName, indexSettings);
es.getClient().admin().indices().create(indexRequest).actionGet();
es.refresh(indexName);
}
private void preapareIndex(String indexName){
if (!es.indexExists(indexName)) {
createIndex(indexName);
}
updateMappings(indexName);
}
模型是这样创建的
@Document(indexName = "#{tenantIndexNamingService.getIndexName()}", type = "movies")
public class Movie {
@Id
@JsonIgnore
private String id;
private String movieTitle;
@CompletionField(maxInputLength = 100)
private Completion movieTitleSuggest;
private String director;
private Date releaseDate;
其中索引名称是通过 SpEl 动态传递的
#{tenantIndexNamingService.getIndexName()}
服务于
@Service
public class TenantIndexNamingService {
private static final String INDEX_PREFIX = "test_index_";
private String indexName = INDEX_PREFIX;
public TenantIndexNamingService() {
}
public String getIndexName() {
return indexName;
}
public void setIndexName(int tenantId) {
this.indexName = INDEX_PREFIX + tenantId;
}
public void setIndexName(String indexName) {
this.indexName = indexName;
}
}
因此,每当我必须执行 CRUD 操作时,首先我指向正确的索引,然后执行所需的操作
tenantIndexNamingService.setIndexName(tenantId);
movieService.save(new Movie("Dead Poets Society", getCompletion("Dead Poets Society"), "Peter Weir", new Date()));
我的假设是以下动态索引分配在多线程 Web 应用程序中无法正常工作:
@Document(indexName = "#{tenantIndexNamingService.getIndexName()}"
这是因为 TenantIndexNamingService 是单例的。
所以我的问题是如何以线程保存方式实现正确的行为?
我可能会采用类似于以下为 Cassandra 提议的方法:
您可以在此处查看相关的 GitHub 存储库:
现在,由于 Elastic 在您定义文档的方式上有所不同,您应该主要关注定义一个请求范围的 bean,它将封装您的租户 ID 并将其绑定到您的传入请求。
这是我的解决方案。我创建了一个 RequestScope bean 来保存每个 HttpRequest
的索引