์—˜๋ผ์Šคํ‹ฑ์„œ์น˜ RestHighLevelClient๋ฅผ ์ด์šฉํ•œ ๋กœ๊ทธ๋ฐฑ ์ปค์Šคํ…€ appender ๋งŒ๋“ค๊ธฐ

AWS์—์„œ ์ œ๊ณตํ•˜๋Š” ES๋ฅผ ์ƒ์šฉ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๊ทธ์‹œ์Šคํ…œ์œผ๋กœ ํ™œ์šฉํ•˜๊ณ  ์žˆ๋Š”๋ฐ ์ตœ๊ทผ ์ฝ”๋กœ๋‚˜ ๋•๋ถ„์— ์žฌํƒ๊ทผ๋ฌด๋ฅผ ํ•˜๋‹ค๋ณด๋‹ˆ ์ธํ”„๋ผํŒ€์—์„œ ํ‚ค๋ฐ”๋‚˜ ์ ‘์†์„ ์ œํ•œํ•˜๋ฉด์„œ ์žฌํƒ๊ทผ๋ฌด ํ•˜๋Š” ๋‚  ์ƒ์šฉ์„œ๋น„์Šค์— ๋Œ€ํ•œ ๋กœ๊ทธํ™•์ธ์ด ๋ถˆ๊ฐ€๋Šฅํ•ด์กŒ๋‹ค. ๊ทธ๋ž˜์„œ ํ‚ค๋ฐ”๋‚˜์— Cognito์„œ๋น„์Šค๋ฅผ ์ ์šฉํ•˜์—ฌ ์ธ์ฆ์„ ํ†ตํ•ด์„œ ํ‚ค๋ฐ”๋‚˜ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ์„ค์ •์„ ํ•˜๊ธด ํ–ˆ๋Š”๋ฐ.....๋กœ๊ทธ๊ฐ€ ๊ธฐ๋ก์ด ์•ˆ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค. ๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” internetitem/logback-elasticsearch-appender ์˜€๋Š”๋ฐ ๊ธฐ๋ณธ์ ์ธ rest api๋ฅผ ํ†ตํ•œ ์ธ๋ฑ์‹ฑ๋งŒ ๊ฐ€๋Šฅํ–ˆ๊ณ  ES์˜ access policy๋ฅผ role ๊ธฐ๋ฐ˜์œผ๋กœ cognito๋ฅผ ์„ค์ •ํ•˜๋ฉด์„œ ์ธ์ฆ๋ฌธ์ œ๋กœ ์ธํ•ด ES๋กœ๊น…์„ ๋ชปํ•˜๊ฒŒ ๋œ ๊ฒƒ์ด๋‹ค. 

๊ทธ๋Ÿผ ์ด ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•ด์•ผ ํ• ๊นŒ ํ•˜๋‹ค๊ฐ€ ๋‚ด๋ฆฐ ๊ฒฐ๋ก ์€ "Elasticsearch์—์„œ ์ œ๊ณตํ•˜๋Š” RestHighLevelClient๋ฅผ ์ด์šฉํ•ด์„œ logback appender๋ฅผ ์ง์ ‘ ๋งŒ๋“ค์–ด์„œ ์จ๋ณด์ง€ ๋ญ~" ์˜€๋‹ค.

์šฐ์„  RestHighLevelClient๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ ค๋ฉด ์•„๋ž˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์„ ์ถ”๊ฐ€ํ•ด์•ผํ•œ๋‹ค. 

compile 'org.elasticsearch:elasticsearch:7.7.1' 
compile 'org.elasticsearch.client:elasticsearch-rest-high-level-client:7.7.1' 
compile 'com.github.awslabs:aws-request-signing-apache-interceptor:deb7941e85' 
compile 'org.elasticsearch:elasticsearch-x-content:7.7.1'

์ด๊ฒƒ๋„ ๊ณต์‹ ์—˜๋ผ์Šคํ‹ฑ์„œ์น˜ ๋ฌธ์„œ๊ฐ€ ์ œ๋Œ€๋กœ ์—…๋ฐ์ดํŠธ ๋˜์–ด์žˆ์ง€ ์•Š๊ฑฐ๋‚˜ ๋ถˆ๋ช…ํ™•ํ•ด์„œ ๋Ÿฐํƒ€์ž„์‹œ์— ์ž๊พธ ์—๋Ÿฌ๋‚˜์„œ ๊ตฌ๊ธ€๋ง ์—ด์‹ฌํžˆ ํ•ด์„œ ์ฐพ์•„๋ƒˆ๋‹ค

์ž, ์ด์ œ AWS Elasticsearch์— access policy๋ฅผ ์–ด๋–ป๊ฒŒ ์„ค์ •ํ–ˆ๋Š”์ง€ ํ•œ๋ฒˆ ๋ณด์ž.

{
   "Version":"2016-10-17",
   "Statement":[
       {"Effect":"Allow",
         "Principal":{
         "AWS":"arn:aws:iam::77345249:role/my-iam-role"},
         "Action":"es:*",
         "Resource":"arn:aws:es:ap-northeast-2:77345249:domain/my-application/*"},
      {"Effect":"Allow",
         "Principal":{
            "AWS":"arn:aws:sts::77345249:assumed-role/Cognito_Role/CognitoIdentityCredentials"},
         "Action":"es:*",
         "Resource":"arn:aws:es:ap-northeast-2:77345249:domain/my-application/*"  }
    ]
}

์œ„ ์ฒ˜๋Ÿผ ์„ค์ •์„ ํ•˜๋ฉด ๊ธฐ์กด์— ์ž˜ ๋™์ž‘ํ•˜๋˜ ElasticsearchAppender๊ฐ€ ๋กœ๊ทธ๋ฅผ ์ œ๋Œ€๋กœ ๋‚จ๊ธฐ์ง€ ๋ชปํ•˜๊ฒŒ ๋œ๋‹ค. (my-iam-role์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ธ์ฆ์„ ํ•ด์•ผ ์ •์ƒ์ ์œผ๋กœ ๋กœ๊น…์„ ํ•  ์ˆ˜ ์žˆ๋‹ค) ๊ทธ๋ž˜์„œ internetitem/logback-elasticsearch-appender ์†Œ์Šค๋ฅผ ์ข€ ๊นŒ ๋ณด์•˜๋”๋‹ˆ ๋‚˜๋ฆ„ AWSAuthentication์ด๋ผ๋Š” ์ธ์ฆ ๊ด€๋ จ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ๊ณ  logback ์„ค์ •์œผ๋กœ BasicAuthentication ๋Œ€์‹ ์— ํ•ด๋‹น ์ธ์ฆ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„์„œ logback ์„ค์ •์— AWSAuthentication์„ ์„ค์ •ํ•ด์ฃผ์—ˆ์ง€๋งŒ region์„ ์ œ๋Œ€๋กœ ๊ฐ€์ ธ์˜ค์ง€ ๋ชปํ•˜๋Š” ๋ฒ„๊ทธ์™€ ํ•จ๊ป˜ CredentialChain์„ Default์–ด์ฉŒ๊ตฌ ์ฒด์ธ์„ ์‚ฌ์šฉํ•˜๊ณ ์žˆ์—ˆ๊ณ  role๊ธฐ๋ฐ˜ ์ธ์ฆ์„ ํ•˜๋„๋ก ์„ค์ •์„ ํ•  ์ˆ˜๊ฐ€ ์—†์—ˆ๋‹ค. ์–ด๋–ป๊ฒŒ๋“  ๊ธฐ์กด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด๋ณด๋ ค๊ณ  ํ•ด๋‹น ์ธ์ฆํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•ด์„œ ๋ณ„๋„์˜ ์ธ์ฆ ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•œ ๋’ค ํ•ด๋‹น ์ธ์ฆ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด๋ณด๋ ค๊ณ  ์‹œ๋„ํ•ด๋ณด์•˜์œผ๋‚˜ ๊ฒฐ๊ตญ signed request๋ฅผ ๋‚ ๋ฆฌ์ง€ ๋ชปํ•˜๊ณ  ์ธ์ฆ์˜ค๋ฅ˜๋กœ ES์—์„œ 400 ์—๋Ÿฌ๋งŒ ์ฃผ๊ตฌ์žฅ์ฐฝ ๋ฐ›์•˜๋‹ค.

๊ทธ๋ž˜์„œ RestHighLevelClient๋ฅผ ์ด์šฉํ•ด์„œ ์ธ๋ฑ์‹ฑ๋ถ€ํ„ฐ ํ•ด๋ณด๊ณ  ๊ทธ๊ฒƒ์„ ๊ธฐ๋ฐ˜์œผ๋กœ logback custom appender๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค. ์šฐ์„  ์ธ๋ฑ์‹ฑํ•˜๋Š” ๊ฒƒ์€ ์—˜๋ผ์Šคํ‹ฑ์„œ์น˜ ๋ฌธ์„œ์— ์นœ์ ˆํ•˜๊ฒŒ ๋‚˜์™€์žˆ๊ธด ํ•˜์˜€์œผ๋‚˜ ์˜ˆ์ œ๊ฐ€ ์ตœ์‹ ํ™”๊ฐ€ ์•ˆ๋˜์–ด์žˆ์–ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€ํ•˜๋Š”๋ฐ๋งŒ๋„ ์‹œ๊ฐ„์„ ๋‚ญ๋น„ํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ES์— ์š”์ฒญํ•˜๋Š” ์ˆœ๊ฐ„!!! cognito๊ฐ€ ์ ์šฉ๋˜์–ด์žˆ์–ด ์ธ์ฆ ์‹คํŒจ!! ๊ทธ๋ž˜์„œ ์œ„ ES access policy statement์˜ ๋งˆ์ง€๋ง‰ ํ•ญ๋ชฉ์œผ๋กœ ์•„๋ž˜์™€ ๊ฐ™์ด ์ •์ฑ…์„ ์ถ”๊ฐ€ํ•ด์„œ ์ž„์‹œ๋กœ ํ—ˆ์šฉํ•ด์ค€๋‹ค.

,
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:ap-northeast-2:72345249:domain/my-application/*"
    }

ํ•ด๋‹น ๋„๋ฉ”์ธ์—์„œ ES๋กœ ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์„ ํ—ˆ์šฉํ•ด์ค€๋‹ค๋Š” ์˜๋ฏธ๋‹ค. 

์—ฌ๊ธฐ๊นŒ์ง€ ์„ฑ๊ณตํ–ˆ๋Š”๋ฐ ์ธ์ฆ์„ ๋„๋Œ€์ฒด ์–ด๋–ค credential์„ ์ด์šฉํ•ด์•ผํ• ์ง€ ๋„ˆ๋ฌด ๋‚œ๊ฐํ–ˆ๋‹ค. ๊ธฐ์กด์— ๊ฒฝ๋ ฅ 20๋…„๊ฐ€๊นŒ์ด ๋œ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์„ฑํ•ด๋†“์€ ์ฝ”๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋Œ์•„๊ฐ€์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฒ˜์Œ๋ถ€ํ„ฐ ํ•˜๋Š” ์‹ฌ์ •์œผ๋กœ ๊ตฌ๊ธ€๋ง์„ ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค. ๋™์‹œ์— aws sdk์˜ ์ธ์ฆ๊ด€๋ จ ํด๋ž˜์Šค๋“ค์„ ํ•˜๋‚˜ํ•˜๋‚˜ ๋ณด๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‹ค๊ฐ€ ๋ˆˆ์— ๋“ค์–ด์˜จ ๋…€์„. ๋ฐ”๋กœ STSAssumeRoleSessionCredentialsProvider ์ด๋‹ค. ์ด ๋…€์„์„ ์ด์šฉํ•ด์„œ ์•„๋ž˜์™€ ๊ฐ™์ด credential์„ ๋ฐ›์•„์˜ค๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ํ•ด๋‹น credential์„ ์ด์šฉํ•ด์„œ ์ธ์ฆ์— ์„ฑ๊ณตํ–ˆ๋‹ค. 

  private AWSCredentialsProvider awsS3CredentialsProvider() {
      List<AWSCredentialsProvider> credentialsProviders = new ArrayList<>();

      String roleSessionName = "role-session-name-" + System.currentTimeMillis();

      credentialsProviders.add(new STSAssumeRoleSessionCredentialsProvider.Builder(roleArn, roleSessionName)
              .withStsClient(AWSSecurityTokenServiceClientBuilder.defaultClient())
              .build());

      return new AWSCredentialsProviderChain(credentialsProviders);
  }

์—ฌ๊ธฐ์„œ roleArn ์ •๋ณด๋งŒ ์žˆ์œผ๋ฉด ๋‚˜๋จธ์ง€๋Š” aws sdk์—์„œ ์•Œ์•„์„œ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์™€์„œ ์ž˜ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค. ์œ ํ›„~~ ์ธ์ฆ์— ์„ฑ๊ณตํ–ˆ์œผ๋‹ˆ ์œ„์—์„œ access policy์— ๋งˆ์ง€๋ง‰์— ์ถ”๊ฐ€ํ–ˆ๋˜ ํ•ญ๋ชฉ์„ ๋‹ค์‹œ ์ง€์›Œ๋„ ๋œ๋‹ค.

ํ•˜์ง€๋งŒ ์œ„ ์ฝ”๋“œ๋ฅผ ์–ป๊ธฐ๊นŒ์ง€ ์•„๋ž˜ ์˜ค๋ฅ˜๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜๋„ ์—†์ด ๋ณด์•˜๋‹ค.

Failed to send events to Elasticsearch: Got response code [403] from server with data {"message":"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method.

Failed to send events to Elasticsearch: Got response code [403] from server with data {"message":"The security token included in the request is expired"}

๊ทธ๋ฆฌ๊ณ  ES์— max ์ƒค๋“œ ๊ฐœ์ˆ˜๊ฐ€ ๊ฝ‰์ฐจ์„œ ๋กœ๊น…์‹œ ์‹ ๊ทœ ์ธ๋ฑ์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ๋„ ์žˆ์—ˆ๋Š”๋ฐ ์ด๋•Œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๊ฐ€ ๋–ด๋‹ค.

Suppressed: org.elasticsearch.client.ResponseException: method [PUT], host [https://vpc-my-application-ig5szafi26tsfulustdplosdu3f4.ap-northeast-2.es.amazonaws.com], URI [/index-2020-06-20/_doc/4ba14a8b96b242d0?timeout=1m], status line [HTTP/1.1 400 Bad Request] {"error":{"root_cause":[{"type":"index_creation_exception","reason":"failed to create index [api-2020-06-20]"}],"type":"validation_exception","reason":"Validation Failed: 1: this action would add [10] total shards, but this cluster currently has [1002]/[1000] maximum shards open;"},"status":400}

ํ‚ค๋ฐ”๋‚˜์—์„œ ์ง์ ‘ PUT myindex-2020-06-20 ๋ช…๋ น์œผ๋กœ ์‹œ๋„ํ•ด๋„ ์‹คํŒจํ–ˆ๊ณ , ์œ„ ์—๋Ÿฌ๋ฉ”์‹œ์ง€์™€ ๋™์ผํ•œ ๋‚ด์šฉ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์œ„์™€ ๊ฐ™์€ ์—๋Ÿฌ๋ฉ”์‹œ์ง€๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด max ์ƒค๋“œ๊ฐœ์ˆ˜๋ฅผ ์˜ฌ๋ ค์ฃผ๋˜์ง€ ์•„๋‹ˆ๋ฉด ๊ธฐ์กด์— ์žˆ๋Š” ์ธ๋ฑ์Šค๋“ค ์ค‘์—์„œ ๋ถˆํ•„์š”ํ•œ ๊ฒƒ๋“ค์„ ์ข€ ๋‚ ๋ ค์ฃผ๋ฉด ๋œ๋‹ค. ์ผ๋ถ€ ์ธ๋ฑ์Šค๋ฅผ ์‚ญ์ œํ•˜๋‹ˆ ๋กœ๊น…์ด ์ž˜ ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋ญ”๊ฐ€ ์ด์ƒํ–ˆ๋‹ค. ํ…Œ์ŠคํŠธ API๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋กœ๊ทธ๊ฐ€ 3๊ฐœ๊ฐ€ ์ฐํ˜€์•ผ๋˜๋Š”๋ฐ 1๊ฐœ๋งŒ ์ฐํžˆ๊ณ  ์žˆ์—ˆ๋‹ค. ๋„๋Œ€์ฒด ๋ญ˜๊นŒ ์–ด๋””๊ฐ€ ๋ฌธ์ œ์ผ๊นŒ ํ•œ์ฐธ์„ ๊ณ ๋ฏผํ•˜๊ณ  ์ด๊ฒƒ์ €๊ฒƒ ์ˆ˜์ •ํ•˜๋ฉด์„œ ํ…Œ์ŠคํŠธ๋ฅผ ํ–ˆ๋‹ค.

์ฒ˜์Œ ๋กœ๊ทธ๋ฉ”์‹œ์ง€ ์ธ๋ฑ์‹ฑ์„ ์œ„ํ•œ ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋Š” ์•„๋ž˜์ฒ˜๋Ÿผ ์ž‘์„ฑํ–ˆ์—ˆ๋‹ค.

  IndexRequest request = new IndexRequest(indexPrefix + LocalDate.now().toString())
          .id(UuidUtil.getTrackingId())
          .source(document);

  Runnable r = () -> {
      try (RestHighLevelClient esClient = esClient()) {
          esClient.index(request, RequestOptions.DEFAULT);
      } catch (Exception e) {
          log.error("ES logging ERROR!!! e-msg:{}", e.getMessage(), e);
      }
  };
  r.run();

์ €๋ ‡๊ฒŒ ์ž‘์„ฑํ•˜๋‹ˆ ์•„๋ฌด ๋ฌธ์ œ์—†์ด ๋กœ๊น…์„ ํ–ˆ์œผ๋‚˜ ๋กœ๊ทธ๊ฐ€ 3๊ฐœ์ค‘ 1๊ฐœ๋งŒ ๊ธฐ๋ก์ด ๋˜๊ณ ์žˆ์—ˆ๋‹ค. ๊ทธ๋ž˜์„œ IndexRequest์˜ create์„ค์ •(default:false)์„ true๋กœ ์ถ”๊ฐ€ํ•ด๋ณด์•˜๋‹ค. ์™ ์ง€ ๋ฎ์–ด์“ฐ๋Š” ๊ฒƒ ๊ฐ™์€ ๋Š๋‚Œ์ด ๋“ค์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋žฌ๋”๋‹ˆ ์•„๋ž˜ "์˜ค๋ฅ˜ 1" ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ์ด ๋˜์—ˆ๊ณ , version ์„ค์ •์„ ํ–ˆ๋”๋‹ˆ ์˜ค๋ฅ˜ 2๊ฐ€ ์ถœ๋ ฅ์ด ๋˜์—ˆ๋‹ค. 

// ์˜ค๋ฅ˜ 1 : create(true) ์ถ”๊ฐ€ํ–ˆ๋”๋‹ˆ
status:CONFLICT, e-msg:Elasticsearch exception [type=version_conflict_engine_exception, reason=[bf0af4cfa5b64945]: version conflict, document already exists (current version [1])]

// ์˜ค๋ฅ˜ 2 : version ์„ค์ •์„ ํ•ด์คฌ๋”๋‹ˆ
create operations do not support explicit versions. use index instead

// ์˜ค๋ฅ˜ 3 : create ์„ค์ •์„ ๋‹ค์‹œ ๋บ๋”๋‹ˆ
internal versioning can not be used for optimistic concurrency control. Please use `if_seq_no` and `if_primary_term` instead

// ์˜ค๋ฅ˜ 4 : ifSeqNo๋งŒ ์„ค์ •ํ–ˆ๋”๋‹ˆ
ifSeqNo is set, but primary term is [0];

// ์˜ค๋ฅ˜ 5 : ifPrimaryTerm๋„ ์„ค์ •ํ–ˆ๋”๋‹ˆ
version conflict, required seqNo [329563504204790], primary term [1592662218337]. but no document was found]

 

ํ•˜๋‚˜ ๋‘˜ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ํ™•์ธํ•˜๋ฉด์„œ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ๋‹ค์‹œ ํ…Œ์ŠคํŠธ ํ•˜๊ธฐ๋ฅผ ๋ช‡ ๋ฒˆ ํ•˜๊ณ ๋‚˜๋‹ˆ ๋™์ผํ•œ ๋ฒ„์ „์œผ๋กœ ์—ฌ๋Ÿฌ ๋„ํ๋จผํŠธ๋ฅผ ์ธ๋ฑ์‹ฑํ•˜๋ ค๋‹ค๊ฐ€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒ(versioning๋ฌธ์ œ)ํ•˜๋Š” ๊ฒƒ์ด๋ผ ์ถ”์ธกํ•  ์ˆ˜ ์žˆ์—ˆ๊ณ , IndexRequest์— ์„ธํŒ…ํ•˜๋Š” ๊ฐ’์— version์ด ์žˆ์–ด์„œ ๊ทธ๊ฒƒ ๋•Œ๋ฌธ์ผ ๊ฑฐ๋ผ ์ƒ๊ฐํ–ˆ์—ˆ์œผ๋‚˜ ๋ฌธ์ œ๋Š” id์˜€๋‹ค. -_-;; ์šฐ์„ , ๋‚˜์˜ ๋ชฉ์ ์€ ๋ชจ๋“  ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธฐ๋ ค๋Š” ๊ฑฐ์˜€๊ณ  ๋„ํ๋จผํŠธ๋ฅผ ๋ฒ„์ €๋‹ํ•ด๊ฐ€๋ฉด์„œ ์—…๋ฐ์ดํŠธ ํ•  ์ผ์€ ์—†๋Š”๋ฐ ์™œ ์ž๊พธ ๋ฒ„์ €๋‹ ๊ด€๋ จ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๋Š” ๊ฒƒ์ผ๊นŒ? ๊ณ ๋ฏผ์„ ์ข€ ํ•˜๋‹ค๊ฐ€ ๋ฐœ๊ฒฌํ•œ ์‚ฌ์‹ค! id๊ฐ’์„ ํŠน์ • ํ”„๋กœ์„ธ์Šค๋ฅผ ํŠธ๋ž˜ํ‚นํ•˜๊ธฐ์œ„ํ•œ ๋˜‘๊ฐ™์€ uuid๊ฐ’์„ ๋„ฃ๊ณ ์žˆ์—ˆ๋˜ ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ id์— ์„ธํŒ…ํ•˜๋Š” ๊ฐ’์„ ์•„๋ž˜์ฒ˜๋Ÿผ ๋‚˜๋…ธ์‹œ๊ฐ„์œผ๋กœ ๋ฐ”๊พธ์–ด์ฃผ์—ˆ๋‹ค.

IndexRequest request = new IndexRequest(indexPrefix + LocalDate.now().toString())
                .id(String.valueOf(System.nanoTime()))
                .source(document);

๊ทธ๋žฌ๋”๋‹ˆ ๋”์ด์ƒ ์˜ค๋ฅ˜๋„ ๋‚˜์ง€ ์•Š๊ณ  ์ธ์ฆ๋„ ์ž˜ํ•˜๊ณ  ์ •์ƒ์ ์œผ๋กœ cognito ์„ค์ •์„ ์™„๋ฃŒํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์‹ค์ œ ์ƒ์šฉ์„œ๋น„์Šค์—์„œ ์‚ฌ์šฉํ•จ์— ์žˆ์–ด์„œ ๋ฒ„๊ทธ๊ฐ€ ์—†๋Š”์ง€ ๋˜๋Š” ์„ฑ๋Šฅ์— ๋ฌธ์ œ๊ฐ€ ์—†์„์ง€๋Š” ๋ถ€ํ•˜ํ…Œ์ŠคํŠธ๋ฅผ ์ข€ ํ•ด๋ด์•ผ๊ฒ ๋‹ค.

ํ™ฉ๊ธˆ๊ฐ™์€ ์ฃผ๋ง์— ์•„๊ฐ€๋ž‘ ๋†€์•„์ฃผ์ง€๋„ ๋ชปํ•˜๊ณ  ์ƒˆ๋ฒฝ๊นŒ์ง€ ์ด๋Ÿฌ๊ณ  ์žˆ๋‹ค๋‹ˆ ใ…œใ…œ

๊ทธ๋ž˜๋„ ํ•ด๊ฒฐ์˜ ์‹ค๋งˆ๋ฆฌ๋ฅผ ์ฐพ์•„์„œ ๊ธฐ์˜๋‹ค. ์”ป๊ณ  ์ž์•ผ๊ฒ ๋‹ค...

 

[6์›” 24์ผ ์—…๋ฐ์ดํŠธ]

๋ถ€ํ•˜ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ try with resource ๊ตฌ๋ฌธํ˜•ํƒœ๋กœ index ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ BAD_REQUEST Unable to parse response body ์™€ ๊ฐ™์€ ์˜ค๋ฅ˜๋‚˜ ์•„๋‹ˆ๋ฉด "You have exceeded the number of permissible concurrent requests with unique IAM Identities. Please retry." ์™€ ๊ฐ™์€ ์˜ค๋ฅ˜๋ฅผ ๋ณด๊ฒŒ๋  ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ƒ์šฉ๋กœ๊ทธ์ฒ˜๋Ÿผ 1์ดˆ๋‚ด์— ์ˆ˜๋ฐฑ~์ˆ˜์ฒœ ๊ฑด์˜ ๋กœ๊ทธ๋ฅผ ์Œ“์•„์•ผ ํ•œ๋‹ค๋ฉด IndexRequest๋Œ€์‹  BulkRequest๋ฅผ bulk๋ฉ”์„œ๋“œ๋กœ ํ˜ธ์ถœํ•˜๋„๋ก ํ•˜๊ณ , try with resource ๊ตฌ๋ฌธ์ด ์•„๋‹Œ client๋ฅผ ํ•œ๋ฒˆ๋งŒ ์ƒ์„ฑํ•œ ๋‹ค์Œ ๊ณ„์† ์žฌ์‚ฌ์šฉํ•˜๋„๋ก ํ•ด์•ผํ•œ๋‹ค. ๊ด€๋ จ๋œ ๋‚ด์šฉ์€ ์•„๋ž˜ ๋ฌธ์„œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html

www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-getting-started-initialization.html

 

[6์›” 30์ผ ์—…๋ฐ์ดํŠธ]

BulkRequest๋„ bulk ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ synchronousํ•˜๊ฒŒ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋กœ๊น…ํ•˜๋Š” ๊ฒƒ์ด ๊ธฐ์กด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง์˜ ์†Œ์š”์‹œ๊ฐ„์— ์˜ํ–ฅ์„ ์ฃผ๊ฒŒ ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ๋กœ๊น…์„ ๋งค์šฐ ๋นˆ๋ฒˆํ•˜๊ฒŒ ํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” bulkAsync ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ bulk ๋ฉ”์„œ๋“œ๋Š” bulkAsync ๋ฉ”์„œ๋“œ๋ณด๋‹ค 2๋ฐฐ์˜ ์„ฑ๋Šฅ ์ €ํ•˜ ํ˜„์ƒ์„ ๊ฐ€์ ธ์˜จ๋‹ค. ํ…Œ์ŠคํŠธ ์‹œ ES๋Š” AWS ES 7.1 ๋ฒ„์ „์œผ๋กœ ํ…Œ์ŠคํŠธํ–ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ํŽ˜์ด์ง€ ์ฒซ ๋ถ€๋ถ„์— ๋ช…์‹œํ–ˆ๋“ฏ์ด 7.7.1 ๋ฒ„์ „์„ ์‚ฌ์šฉํ–ˆ๋‹ค.

 

[7์›” 7์ผ ์—…๋ฐ์ดํŠธ]

์„ธ ๊ฐ€์ง€ ์ด์Šˆ๊ฐ€ ์ถ”๊ฐ€๋กœ ๋ฐœ๊ฒฌ๋˜์—ˆ๋‹ค.

 

์ฒซ ๋ฒˆ์งธ, 6์›” 24์ผ ์—…๋ฐ์ดํŠธ์— ๋‚˜์™”๋˜ ๋ฌธ์ œ๊ฐ€ ๋˜ ๋‚˜์™”๋‹ค. 

method [POST], host [https://vpc-elasticsearch.ap-northeast-2.es.amazonaws.com], URI [/_bulk?timeout=1m], status line [HTTP/1.1 400 Bad Request]
{"Message":"You have exceeded the number of permissible concurrent requests with unique IAM Identities. Please retry."}

์ด๋ฒˆ์—๋Š” ์†Œ์Šค๋ ˆ๋ฒจ์—์„œ ๋งŽ์€ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‚ฌ์šฉํ•œ๊ฒŒ ์•„๋‹ˆ์—ˆ์ง€๋งŒ, AWS ์ฝ˜์†”์— ์ ‘์†ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋งŽ์„ ๊ฒฝ์šฐ ์ข…์ข… ๋ฐœ์ƒํ•œ๋‹ค. ์ด ๋ถ€๋ถ„์„ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„๊นŒ ๊ณ ๋ฏผ์„ ํ•ด๋ณด์•„๋„ ์ด ๋ถ€๋ถ„๊นŒ์ง€ ์ปจํŠธ๋กค ํ•  ์ˆ˜๋Š” ์—†์„ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ ๋‹ค.

 

๋‘ ๋ฒˆ์งธ, ์˜๋„์น˜ ์•Š๊ฒŒ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ข…๋ฃŒ๋˜๋Š” ํ˜„์ƒ์ด ๊ฐœ๋ฐœ์„œ๋ฒ„์—์„œ ๋ฐœ๊ฒฌ๋˜์—ˆ๋‹ค.

IllegalStateExceptionRequest cannot be executed; I/O reactor status: STOPPED

์ด๊ฑด ์˜ˆ์™ธ๋ฅผ ์žก์•„์„œ ์ƒˆ๋กœ์šด ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๋„๋ก ์ˆ˜์ •ํ•˜๊ธด ํ–ˆ์œผ๋‚˜....์™œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ข…๋ฃŒ๋˜์—ˆ๋Š”์ง€ ์•Œ ์ˆ˜๊ฐ€ ์—†์–ด ๋‹ต๋‹ตํ•˜๋‹ค.

 

์„ธ ๋ฒˆ์งธ, ๋ถ€ํ•˜๋ฅผ ๋งŽ์ด ์ค€ ์ธ์Šคํ„ด์Šค์—์„œ ์•„๋ž˜์™€ ๊ฐ™์€ ์˜ค๋ฅ˜ ๋ฐœ์ƒ (thread: I/O dispatcher 2)

Connection lease request time out:
at org.apache.http.nio.pool.AbstractNIOConnPool.processPendingRequest(AbstractNIOConnPool.java:411)
at org.apache.http.nio.pool.AbstractNIOConnPool.processNextPendingRequest(AbstractNIOConnPool.java:391)
at org.apache.http.nio.pool.AbstractNIOConnPool.release(AbstractNIOConnPool.java:355)
at org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager.releaseConnection(PoolingNHttpClientConnectionManager.java:364)
at org.apache.http.impl.nio.client.AbstractClientExchangeHandler.releaseConnection(AbstractClientExchangeHandler.java:245)
at org.apache.http.impl.nio.client.MainClientExec.responseCompleted(MainClientExec.java:387)
at org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl.responseCompleted(DefaultClientExchangeHandlerImpl.java:172)
at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.processResponse(HttpAsyncRequestExecutor.java:448)
at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.inputReady(HttpAsyncRequestExecutor.java:338)
at org.apache.http.impl.nio.client.InternalRequestExecutor.inputReady(InternalRequestExecutor.java:83)
at org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:265)
at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:81)
at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:39)
at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:121)
at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:162)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:337)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276)
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:591)
at java.lang.Thread.run(Thread.java:748)

 

 

 

์ฐธ๊ณ ์ž๋ฃŒ:

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/master/java-rest-high-document-index.html http://logback.qos.ch/manual/appenders.html