AWS / Lambda / Java上的Elasticsearch客户端-2.5秒的客户端启动时间

时间:2019-03-04 16:27:09

标签: java amazon-web-services elasticsearch

我们正在使用AWS Lambda(Java)和elasticsearch客户端连接到AWS上的托管Elasticsearch实例。我在大约2.5秒的第一次请求上遇到了漫长的等待时间(冷启动时)。之后,它很快。我真的无法弄清楚这种延迟来自哪里,我正在尝试对其进行优化。

private void testPerformanceElasticSearch() throws Exception {
        log.info("1. Before testing elasticsearch client");
        AWS4Signer signer = new AWS4Signer();
        signer.setServiceName("es");
        signer.setRegionName("eu-west-1");
        HttpRequestInterceptor interceptor = new AWSRequestSigningApacheInterceptor("es", signer, new DefaultAWSCredentialsProviderChain());
        String endpoint = "https://" + Utils.getEnvironmentVariable("ELASTIC_SEARCH_ENDPOINT");
        RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(HttpHost.create(endpoint)).setHttpClientConfigCallback(hacb -> hacb.addInterceptorLast(interceptor)));
        log.info("2. After getting elasticsearch client");
        log.info("3. Before doing a elasticsearch query");
        log.info("4");
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        log.info("5");
        TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("userId", "abc");
        log.info("6");
        boolQueryBuilder.must(termsQueryBuilder);
        log.info("7");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        log.info("8");
        searchSourceBuilder.query(boolQueryBuilder);
        log.info("9");
        SearchRequest searchRequest = new SearchRequest("users");
        log.info("10");
        searchRequest.source(searchSourceBuilder);
        log.info("11");
        restHighLevelClient.search(searchRequest);
        log.info("12");
        log.info("13. After testing elasticsearch");
}

然后我得到这样的日志记录;您会看到在“ 5”到“ 6”之间有超过2秒的延迟,我无法真正放置该延迟:

17:16:06.871INFO[PlacesPerformance] 1. Before testing elasticsearch client
17:16:06.932INFO[PlacesPerformance] 2. After getting elasticsearch client
17:16:06.933INFO[PlacesPerformance] 3. Before doing a elasticsearch query
17:16:06.935INFO[PlacesPerformance] 4
17:16:06.942INFO[PlacesPerformance] 5
17:16:09.179INFO[PlacesPerformance] 6
17:16:09.179INFO[PlacesPerformance] 7
17:16:09.181INFO[PlacesPerformance] 8
17:16:09.181INFO[PlacesPerformance] 9
17:16:09.183INFO[PlacesPerformance] 10
17:16:09.183INFO[PlacesPerformance] 11
17:16:09.362INFO[PlacesPerformance] 12
17:16:09.362INFO[PlacesPerformance] 13. After testing elasticsearch

关于如何改善这一点的任何建议?

更新:

奇怪。每当我在lambda中运行代码时,在构造请求(甚至不执行请求)时都会遇到2.5秒的延迟。在本地,它工作正常。我尝试了以下方法:

1.  Local against local elasticsearch. No delay.
2.  Local against AWS elasticsearch. No delay.
3.  Lambda with signing request. DELAY.
4.  Lambda without signing request. DELAY.
5.  Lambda with a 'match all' query. DELAY
6.  Lambda with a http address. DELAY.
7.  Lambda with a custom runtime. DELAY.
8.  Lambda with a custom runtime. DELAY.
9.  Lambda with standard Java 8 runtime. DELAY.

2 个答案:

答案 0 :(得分:4)

问题在于,在第一个请求(实际请求,不是预热请求,因为预热请求不会通过您的应用程序代码,它不会触发实际请求路径中使用的加载类)JVM加载(读取,解析,验证等)相关类,初始化安全组件(密码等),并完成TLS握手(需要多个RTT,对于Java 9和TLS 1.3,应减少此操作)。

对于第一个AWS服务调用(DynamoDB,SQS等),也看到了类似的长时间行为

由于我是Thundra热身插件的作者,我正在考虑引入热身消息的挂钩点,因为自定义操作将能够执行,例如初始化安全组件,加载类等...

答案 1 :(得分:1)

VPC中的Lambda函数对启动时间有很大的影响。您说您的ES是托管实例,所以我认为它是由VPC支持的。

即使本质上,即使不在VPC中,Java冷启动通常也比Node或Python这样的运行时更长,因为JVM需要首先启动。这主要是您的2.5秒来自哪里。

好。如何解决该问题?

这取决于与ElasticSearch所需的并发连接数。如果一个函数能够处理所有传入的请求,则可以将Lambda函数的并发执行限制为1,因此请确保始终命中同一容器(只要这些请求在±5分钟内发出)时间范围)。

现在,如果您不预先知道将执行多少个并行Lambda函数,那么您将毫无出路。您可以尝试预先预热Lambda函数,但随后需要同时触发100个请求来预热100个不同的容器。

在我通过Lambda函数的并发模型以及冷/暖如何开始工作时,请检查this answer

如果您有更多信息要分享或我不够清楚,我很乐意编辑我的答案。