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

的索引