<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>제로부터시작하는개발생활</title>
    <link>https://baektothefuture.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Fri, 10 Apr 2026 12:02:16 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>baektothefuture</managingEditor>
    <item>
      <title>파이썬 알고리즘 문제풀이 : collections.Counter</title>
      <link>https://baektothefuture.tistory.com/26</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬에서 자주 등장하는 라이브러리 중 하나인 collections에는 아주 유용한 자료구조인 Counter가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;collections.Counter란?&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Counter는 파이썬의 내장 모듈 collections에 포함된 특수한 딕셔너리입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리스트, 문자열 같은 반복 가능한(iterable) 객체를 받아, 각 요소가 몇 번 등장했는지를 세어주는 자료형입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1748431532024&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from collections import Counter

arr = ['a', 'b', 'a', 'c', 'b', 'a']

counter = Counter(arr)
print(counter)
## 결과 : Counter({'a': 3, 'b': 2, 'c': 1})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 요소를 key로, 등장 횟수를 value로 저장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Counter 끼리 산술 연산이 가능합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1748431598419&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;a = Counter(['a', 'b', 'c', 'a'])
b = Counter(['a', 'b'])
print(a - b)  # 결과: Counter({'a': 1, 'c': 1})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 같은 key에 대해 개수를 빼줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 결과가 0 이하인 항목은 자동으로 제거됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Counter는 딕셔너리 처럼 동작합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1748431788275&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;return list(answer.keys())[0]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 딕셔너리의 .keys()를 통해 이름만 추출할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;개념&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;정리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;collections.Counter&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;리스트에서 각 요소의 등장 횟수를 세어주는 딕셔너리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;산술연산 가능 : Counter(A) - Counter(B)&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;A에서 B의 항목 수를 빼고 남은 것만 반환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;딕셔너리 처럼 동작 : .keys()&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;딕셔너리 메서드 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
      <category>python</category>
      <category>Collections</category>
      <category>파이썬</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/26</guid>
      <comments>https://baektothefuture.tistory.com/26#entry26comment</comments>
      <pubDate>Wed, 28 May 2025 20:31:49 +0900</pubDate>
    </item>
    <item>
      <title>APM Agent</title>
      <link>https://baektothefuture.tistory.com/25</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Elasticsearch에 Http Request를 보낼 때 계측하여 모니터링 할 수 있도록 APM을 테스트 및 개발중이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복기 겸,, 개발 가능성 유무를 확고히 하기 위해 기록..합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 환경 : 각 노드에 Elastic Agent가 설치&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Elastic APM&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Fleet 이란?&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Agent Server를 관리하며 정책을 부여&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Elastic APM 이란?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;incoming requests, database queries, caches, external HTTP request, ... 등등 수집&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디버깅 시 발생하는 로그 수집&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Elastic APM은 APM Agent 역할을 함과 동시에 APM Server 역할도 가능하다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Kibana에서 확인할 수 있는 로그 저장소 - data_stream&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;APM은 Metrics를 &lt;b&gt;ILM&lt;/b&gt;(Index Lifecycle Management)을 활용하여 데이터를 관리한다.&lt;br /&gt;- Application traces : `traces-apm.internal-&amp;lt;namespace&amp;gt;`&amp;nbsp;&amp;nbsp;&amp;rarr;&amp;nbsp;&amp;nbsp;traces-apm-default&lt;br /&gt;-&amp;nbsp;APM&amp;nbsp;internal&amp;nbsp;metrics:&amp;nbsp;`metrics-apm.internal-&amp;lt;namespace&amp;gt;`&amp;nbsp;&amp;nbsp;&amp;rarr;&amp;nbsp;metrics-apm.internal-default&lt;br /&gt;- APM transaction metrics: `metrics-apm.transaction.&amp;lt;metricset.interval&amp;gt;-&amp;lt;namespace&amp;gt;`&lt;br /&gt;-&amp;nbsp;APM&amp;nbsp;service&amp;nbsp;destination&amp;nbsp;metrics:&amp;nbsp;`metrics-apm.service_destination.&amp;lt;metricset.interval&amp;gt;-&amp;lt;namespace&amp;gt;`&lt;br /&gt;-&amp;nbsp;APM&amp;nbsp;service&amp;nbsp;transaction&amp;nbsp;metrics:&amp;nbsp;`metrics-apm.service_transaction.&amp;lt;metricset.interval&amp;gt;-&amp;lt;namespace&amp;gt;`&lt;br /&gt;-&amp;nbsp;APM&amp;nbsp;service&amp;nbsp;summary&amp;nbsp;metrics:&amp;nbsp;`metrics-apm.service_summary.&amp;lt;metricset.interval&amp;gt;-&amp;lt;namespace&amp;gt;`&lt;br /&gt;- Application metrics: `metrics-apm.app.&amp;lt;service.name&amp;gt;-&amp;lt;namespace&amp;gt;`&lt;br /&gt;&amp;nbsp; &amp;nbsp; 출처 : &lt;a href=&quot;https://www.elastic.co/guide/en/observability/current/apm-data-streams.html&quot;&gt;https://www.elastic.co/guide/en/observability/current/apm-data-streams.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1747740808643&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Data streams | Elastic Docs&quot; data-og-description=&quot;APM data follows the &amp;lt;type&amp;gt;-&amp;lt;dataset&amp;gt;-&amp;lt;namespace&amp;gt; naming scheme. The type and dataset are predefined by the Elasticsearch apm-data plugin, but the namespace...&quot; data-og-host=&quot;www.elastic.co&quot; data-og-source-url=&quot;https://www.elastic.co/guide/en/observability/current/apm-data-streams.html&quot; data-og-url=&quot;https://www.elastic.co/docs/solutions/observability/apm/data-streams&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/vwcVW/hyYYCxQY7G/KGYhwmsO1BVa581n32RVBk/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot;&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/observability/current/apm-data-streams.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.elastic.co/guide/en/observability/current/apm-data-streams.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/vwcVW/hyYYCxQY7G/KGYhwmsO1BVa581n32RVBk/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Data streams | Elastic Docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;APM data follows the &amp;lt;type&amp;gt;-&amp;lt;dataset&amp;gt;-&amp;lt;namespace&amp;gt; naming scheme. The type and dataset are predefined by the Elasticsearch apm-data plugin, but the namespace...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.elastic.co&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Elasticsearch에 Http Request를 날리는 어플리케이션에서 헤더에 특정 id를 포함하여 전송하면 해당 task를 키바나의 트랜잭션(APM -&amp;gt; Servcie -&amp;gt; Transactions)에서 감지 가능할까?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; NO : Elasticsearch는 Tracer 인스턴스를 상속받아야 인식가능한 Task로 변환된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/elastic/elasticsearch/blob/main/TRACING.md#how-to-i-trace-something-that-isnt-a-task&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/elastic/elasticsearch/blob/main/TRACING.md#how-to-i-trace-something-that-isnt-a-task&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1747741037590&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;elasticsearch/TRACING.md at main &amp;middot; elastic/elasticsearch&quot; data-og-description=&quot;Free and Open Source, Distributed, RESTful Search Engine - elastic/elasticsearch&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/elastic/elasticsearch/blob/main/TRACING.md#how-to-i-trace-something-that-isnt-a-task&quot; data-og-url=&quot;https://github.com/elastic/elasticsearch/blob/main/TRACING.md&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/btTuXK/hyYU3cNV9w/lKIqUTTQPwW6bvTykZj6G0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bCqVW9/hyYTig896W/M3KqtafFxkEJWqc3VeHwa1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/elastic/elasticsearch/blob/main/TRACING.md#how-to-i-trace-something-that-isnt-a-task&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/elastic/elasticsearch/blob/main/TRACING.md#how-to-i-trace-something-that-isnt-a-task&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/btTuXK/hyYU3cNV9w/lKIqUTTQPwW6bvTykZj6G0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bCqVW9/hyYTig896W/M3KqtafFxkEJWqc3VeHwa1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;elasticsearch/TRACING.md at main &amp;middot; elastic/elasticsearch&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Free and Open Source, Distributed, RESTful Search Engine - elastic/elasticsearch&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;어플리케이션 모니터링 -&amp;nbsp;&amp;nbsp;APM Service 생성&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;환경 : IDE (Intellij)&lt;br /&gt;언어 : Java&lt;br /&gt;&lt;br /&gt;&lt;b&gt;설정&lt;/b&gt;&lt;br /&gt;-&amp;nbsp;Run/Deug&amp;nbsp;Configurations&amp;nbsp;(IDE)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;Modify&amp;nbsp;options를&amp;nbsp;통해&amp;nbsp;환경변수&amp;nbsp;설정&amp;nbsp;추가&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-javaagent:C:\Users\&amp;lt;사용자&amp;gt;\IdeaProjects\&amp;lt;프로젝트&amp;gt;\src\elastic-apm-agent-1.53.0.jar&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(다운받은&amp;nbsp;agent&amp;nbsp;주소)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-Delastic.apm.service_name=seonmin&amp;nbsp;(서비스&amp;nbsp;이름)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-Delastic.apm.server_url=http://192.168.125.69:8200&amp;nbsp;(apm&amp;nbsp;서버&amp;nbsp;주소)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-Delastic.apm.environment=dev&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-Delastic.apm.application_packages=controller&amp;nbsp;(source&amp;nbsp;project가&amp;nbsp;속해&amp;nbsp;있는&amp;nbsp;상위&amp;nbsp;폴더)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;주요 코드&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/apm/agent/java/current/public-api.html&quot;&gt;https://www.elastic.co/guide/en/apm/agent/java/current/public-api.html&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/apm/agent/java/current/method-api.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.elastic.co/guide/en/apm/agent/java/current/method-api.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;pom.xml&lt;/h4&gt;
&lt;pre id=&quot;code_1747741678377&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    &amp;lt;dependency&amp;gt;
      &amp;lt;groupId&amp;gt;co.elastic.apm&amp;lt;/groupId&amp;gt;
      &amp;lt;artifactId&amp;gt;apm-agent-api&amp;lt;/artifactId&amp;gt;
      &amp;lt;version&amp;gt;1.52.0&amp;lt;/version&amp;gt;
    &amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;.java&lt;/h4&gt;
&lt;pre id=&quot;code_1747741739359&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Span span = ElasticApm.currentSpan();
Transaction transaction = ElasticApm.startTransaction();
try {
    transaction.setName(&quot;서비스 이름&quot;);
    transaction.setType(Transaction.TYPE_REQUEST);

    &amp;lt;code...&amp;gt;

    } catch(Exception e) {
        transaction.captureException(e);
        throw e;
    } finally {
	    transaction.end();
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;&lt;b&gt;서비스 이름을 임의로 지정하여 테스트&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1029&quot; data-origin-height=&quot;423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ln92d/btsN4saK8HF/6H8BTeUAOXAueB51zHdPD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ln92d/btsN4saK8HF/6H8BTeUAOXAueB51zHdPD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ln92d/btsN4saK8HF/6H8BTeUAOXAueB51zHdPD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fln92d%2FbtsN4saK8HF%2F6H8BTeUAOXAueB51zHdPD0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1029&quot; height=&quot;423&quot; data-origin-width=&quot;1029&quot; data-origin-height=&quot;423&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring 프레임워크의 경우 더욱 간단하게 어플리케이션 로그를 남길 수 있다.&lt;br /&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/apm/agent/java/current/setup-attach-api.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.elastic.co/guide/en/apm/agent/java/current/setup-attach-api.html&lt;/a&gt;&lt;br /&gt;지원되는 프레임워크&lt;br /&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/apm/agent/java/current/supported-technologies-details.html#supported-java-versions&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.elastic.co/guide/en/apm/agent/java/current/supported-technologies-details.html#supported-java-versions&lt;/a&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;</description>
      <category>Elasticsearch</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/25</guid>
      <comments>https://baektothefuture.tistory.com/25#entry25comment</comments>
      <pubDate>Tue, 20 May 2025 20:52:00 +0900</pubDate>
    </item>
    <item>
      <title>elasticsearch 한글 형태소 분석사전</title>
      <link>https://baektothefuture.tistory.com/24</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;기본 개념&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://esbook.kimjmin.net/06-text-analysis/6.7-stemming/6.7.2-nori&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://esbook.kimjmin.net/06-text-analysis/6.7-stemming/6.7.2-nori&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1743504515499&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;6.7.2 노리 (nori) 한글 형태소 분석기 | Elastic 가이드북&quot; data-og-description=&quot;이 문서의 허가되지 않은 무단 복제나 배포 및 출판을 금지합니다. 본 문서의 내용 및 도표 등을 인용하고자 하는 경우 출처를 명시하고 김종민(kimjmin@gmail.com)에게 사용 내용을 알려주시기 바랍&quot; data-og-host=&quot;esbook.kimjmin.net&quot; data-og-source-url=&quot;https://esbook.kimjmin.net/06-text-analysis/6.7-stemming/6.7.2-nori&quot; data-og-url=&quot;https://esbook.kimjmin.net/06-text-analysis/6.7-stemming/6.7.2-nori&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eh0Ybb/hyYBfXnmiL/jP1Ktc3j6gBJl8HKk7Ynq1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/7cNqL/hyYxRYanx9/ddHRtRnQA3Ht4sO9gW6Mok/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/4aU7V/hyYyK47nb5/zN5qYHHhVkngQTIFKaNhgk/img.png?width=1280&amp;amp;height=630&amp;amp;face=0_0_1280_630&quot;&gt;&lt;a href=&quot;https://esbook.kimjmin.net/06-text-analysis/6.7-stemming/6.7.2-nori&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://esbook.kimjmin.net/06-text-analysis/6.7-stemming/6.7.2-nori&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eh0Ybb/hyYBfXnmiL/jP1Ktc3j6gBJl8HKk7Ynq1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/7cNqL/hyYxRYanx9/ddHRtRnQA3Ht4sO9gW6Mok/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/4aU7V/hyYyK47nb5/zN5qYHHhVkngQTIFKaNhgk/img.png?width=1280&amp;amp;height=630&amp;amp;face=0_0_1280_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;6.7.2 노리 (nori) 한글 형태소 분석기 | Elastic 가이드북&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 문서의 허가되지 않은 무단 복제나 배포 및 출판을 금지합니다. 본 문서의 내용 및 도표 등을 인용하고자 하는 경우 출처를 명시하고 김종민(kimjmin@gmail.com)에게 사용 내용을 알려주시기 바랍&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;esbook.kimjmin.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 글에 따르면 Nori는 한국어 텍스트 분석을 위해 설계되었으며 Elasticsearch 공식 분석기 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주요 특징&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 일반 명사, 고유 명사만 등록 ( 한글의 경우 명사, 동명사 정도만 검색 )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Nori는 기본적으로 품사 필터링을 통해 조사, 접미사 등 17개 품사를 제거(default)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;stoptags&lt;/b&gt;&lt;span style=&quot;background-color: #feffff; color: #111e2b; text-align: start;&quot;&gt; 값에 배열로 제외할 품사 코드를 나열해서 입력&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;벤치 마크 및 알고리즘&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #feffff; color: #111e2b; text-align: start;&quot;&gt;&lt;a href=&quot;https://www.elastic.co/kr/blog/nori-the-official-elasticsearch-plugin-for-korean-language-analysis&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.elastic.co/kr/blog/nori-the-official-elasticsearch-plugin-for-korean-language-analysis&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1743507676640&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;공식 한국어 분석 플러그인 &amp;ldquo;노리&amp;rdquo;&quot; data-og-description=&quot;6.4에 추가된 Elasticsearch 공식 한국어 분석 플러그인 &amp;ldquo;노리&amp;rdquo;에 대한 모든 것...&quot; data-og-host=&quot;www.elastic.co&quot; data-og-source-url=&quot;https://www.elastic.co/kr/blog/nori-the-official-elasticsearch-plugin-for-korean-language-analysis&quot; data-og-url=&quot;https://www.elastic.co/kr/blog/nori-the-official-elasticsearch-plugin-for-korean-language-analysis&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b2PchR/hyYxJMzi67/RKXAxHIVeYnR1JOTNRfpx0/img.jpg?width=720&amp;amp;height=420&amp;amp;face=0_0_720_420,https://scrap.kakaocdn.net/dn/9Q6Um/hyYBdZz8m1/k9qqbZqMkZ8q8KkWMcdyOk/img.jpg?width=720&amp;amp;height=420&amp;amp;face=0_0_720_420,https://scrap.kakaocdn.net/dn/9eZdX/hyYBiGzWQP/f13k3ePevfMsNpdJXKNA2K/img.png?width=1553&amp;amp;height=1600&amp;amp;face=0_0_1553_1600&quot;&gt;&lt;a href=&quot;https://www.elastic.co/kr/blog/nori-the-official-elasticsearch-plugin-for-korean-language-analysis&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.elastic.co/kr/blog/nori-the-official-elasticsearch-plugin-for-korean-language-analysis&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b2PchR/hyYxJMzi67/RKXAxHIVeYnR1JOTNRfpx0/img.jpg?width=720&amp;amp;height=420&amp;amp;face=0_0_720_420,https://scrap.kakaocdn.net/dn/9Q6Um/hyYBdZz8m1/k9qqbZqMkZ8q8KkWMcdyOk/img.jpg?width=720&amp;amp;height=420&amp;amp;face=0_0_720_420,https://scrap.kakaocdn.net/dn/9eZdX/hyYBiGzWQP/f13k3ePevfMsNpdJXKNA2K/img.png?width=1553&amp;amp;height=1600&amp;amp;face=0_0_1553_1600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;공식 한국어 분석 플러그인 &amp;ldquo;노리&amp;rdquo;&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;6.4에 추가된 Elasticsearch 공식 한국어 분석 플러그인 &amp;ldquo;노리&amp;rdquo;에 대한 모든 것...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.elastic.co&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;형태소 분석 과정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 입력 문장 처리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;형태소 분석은 입력된 텍스트를 어절 단위로 나눕니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시) &quot;21세기 세종계획&quot; -&amp;gt; &quot;21 + 세기 + 세종 + 계획&quot; 혹은 &quot;21 + 세 + 기세 + 종계 + 획&quot; 등&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 비용 계산 알고리즘&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Viterbi 알고리즘을 사용하여 각 분할 경로의 비용을 계산합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 비용은 형태소 간 전이 비용과 형태소 자체의 비용으로 구성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 비용이 낮을수록 더 자연스러운 분할로 간주&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 위의 예시로는 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&quot;21 + 세기 + 세종 + 계획&quot;&lt;span&gt;&amp;nbsp;이 가장 낮은 비용으로 선택될 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 처리 최적화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 노리는 입력 텍스트를 글자 단위로 처리하며, 실시간으로 격자를 생성하고 비용을 계산한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 특정 상태에서 가능한 전이가 하나뿐일 때는 즉시 결과를 출력하여 처리 속도를 높인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 바이너리 사전 활용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: oklch(0.99 0.004 106.471); color: oklch(0.304 0.04 213.681); text-align: left;&quot;&gt;- 노리는 MeCab-ko-dic 사전을 바이너리 형식으로 압축하여 효율적으로 검색합니다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: oklch(0.99 0.004 106.471); color: oklch(0.304 0.04 213.681); text-align: left;&quot;&gt;&amp;nbsp; (&lt;span style=&quot;background-color: oklch(0.99 0.004 106.471); color: oklch(0.304 0.04 213.681); text-align: left;&quot;&gt;FST(Finite State Transducer)를 사용해 빠르게 검색)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #feffff; color: #111e2b; text-align: start;&quot;&gt;유의사항&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #feffff; color: #111e2b; text-align: start;&quot;&gt;- 사용자 사전이 기본사전보다 항상 우위&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #feffff; color: #111e2b; text-align: start;&quot;&gt;- 최장일치 우선 등록 / 우선 분석 이슈&lt;/span&gt;&lt;/p&gt;</description>
      <category>Elasticsearch</category>
      <category>Elasticsearch</category>
      <category>NORI</category>
      <category>분석사전</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/24</guid>
      <comments>https://baektothefuture.tistory.com/24#entry24comment</comments>
      <pubDate>Tue, 1 Apr 2025 20:51:52 +0900</pubDate>
    </item>
    <item>
      <title>profile을 통해 실제 쿼리가 어떻게 구성되는지 확인해보기</title>
      <link>https://baektothefuture.tistory.com/23</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예시 데이터&lt;/b&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;id&quot;: &quot;park_rocky-mountain&quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;title&quot;: &quot;Rocky Mountain&quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;description&quot;: &quot;Bisected north to south by the Continental Divide, this portion of the Rockies has ecosystems varying from over 150 riparian lakes to montane and subalpine forests to treeless alpine tundra.&quot;
}&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&quot;profile&quot;을 통해 실제 쿼리가 어떻게 진행되는지 확인&lt;/blockquote&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;필드 미지정 시 Query?&lt;/b&gt;&lt;/h4&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;GET my-index/_search
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;profile&quot;: true,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;query&quot;: {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;query_string&quot;: {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;query&quot;:&amp;nbsp;&amp;nbsp;&quot;(\&quot;park\&quot;)&quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1436&quot; data-origin-height=&quot;264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ddHczH/btsMZyaIbUp/pa5Q5nT99cGVjKH6GiJaLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ddHczH/btsMZyaIbUp/pa5Q5nT99cGVjKH6GiJaLK/img.png&quot; data-alt=&quot;description 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ddHczH/btsMZyaIbUp/pa5Q5nT99cGVjKH6GiJaLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FddHczH%2FbtsMZyaIbUp%2Fpa5Q5nT99cGVjKH6GiJaLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1436&quot; height=&quot;264&quot; data-origin-width=&quot;1436&quot; data-origin-height=&quot;264&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;description 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: center;&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;u&gt;&lt;b&gt;필드 미지정 시 모든 필드에 search를 하는것을 확인&lt;/b&gt;&lt;/u&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;괄호 밖과 안에서 서로 다른 필드 지정&lt;/b&gt;&lt;/h4&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;case 1:&lt;/b&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;GET my-index/_search
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;profile&quot;: true,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;query&quot;: {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;query_string&quot;: {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;query&quot;:&amp;nbsp;&amp;nbsp;&quot;id:(\&quot;park\&quot;)&quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1332&quot; data-origin-height=&quot;250&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vExIC/btsMYtnTZsm/YQTcKUGf08I8NvoZm1h8dK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vExIC/btsMYtnTZsm/YQTcKUGf08I8NvoZm1h8dK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vExIC/btsMYtnTZsm/YQTcKUGf08I8NvoZm1h8dK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvExIC%2FbtsMYtnTZsm%2FYQTcKUGf08I8NvoZm1h8dK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1332&quot; height=&quot;250&quot; data-origin-width=&quot;1332&quot; data-origin-height=&quot;250&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;case 2:&lt;/b&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;GET my-index/_search
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;profile&quot;: true,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;query&quot;: {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;query_string&quot;: {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;query&quot;:&amp;nbsp;&amp;nbsp;&quot;id:((\&quot;park\&quot;) AND title:(\&quot;mountain\&quot;))&quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/U1Mf1/btsMZhtvdM6/hF5Gma4lLSFx8AJLJVv1nk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/U1Mf1/btsMZhtvdM6/hF5Gma4lLSFx8AJLJVv1nk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/U1Mf1/btsMZhtvdM6/hF5Gma4lLSFx8AJLJVv1nk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FU1Mf1%2FbtsMZhtvdM6%2FhF5Gma4lLSFx8AJLJVv1nk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1246&quot; height=&quot;280&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;br&gt;profile 결과는 각 쿼리 단계별로 소요된 시간과 리소스 사용량을 JSON 형태로 제공합니다. &lt;br&gt;이를 통해 어떤 부분이 성능 저하를 유발하는지 파악하고, 인덱스 구조나 쿼리 문법을 최적화할 수 있습니다.&lt;br&gt;&lt;br&gt;활용 방안:&lt;br&gt; • 인덱스 최적화: 자주 검색되는 필드나 패턴을 파악하여, 해당 필드에 대한 인덱싱 전략을 조정할 수 있습니다.&lt;br&gt; • 쿼리 구조 개선: 불필요한 복잡한 쿼리 구조를 단순화하거나, 효율적인 검색 연산자로 변경하여 성능을 향상시킬 수 있습니다.&lt;br&gt;&lt;br&gt;&lt;/p&gt;</description>
      <category>Elasticsearch</category>
      <category>Elasticsearch</category>
      <category>query</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/23</guid>
      <comments>https://baektothefuture.tistory.com/23#entry23comment</comments>
      <pubDate>Thu, 27 Mar 2025 20:59:30 +0900</pubDate>
    </item>
    <item>
      <title>인덱스 샤드 설정에 대해</title>
      <link>https://baektothefuture.tistory.com/22</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;유튜브 데이터에 특화된 분석기가 업데이트되어 데이터를 재색인 해야하는 일이 생겼다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이로인해 새로운 인덱스를 생성해야 했는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정에서 샤드를 어느정도 설정해야 이상적일까에 대해 생각해보았다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;사용환경 : 크론탭&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;유튜브 데이터의 하루 색인량은 약 1000건이며 기능 명세상 사용자 쿼리에 의해 업데이트되는 기능은 아니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Elasticsearch Shard에 대해&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Elasticsearch 쿼리는 샤드당 단일 스레드로 실행된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;각각의 Shard는 Lucene 인덱스의 인스턴스이며 Lucene 인덱스는 내부적으로 다수의 세그먼트로 구성되어 있다.&lt;/li&gt;
&lt;li&gt;노드가 더 많은 힙공간을 가질수록 처리할 수 있는 데이터와 샤드가 늘어난다.&lt;/li&gt;
&lt;li&gt;시계열 데이터 기준 적정 샤드 크기는 10GB~50GB이다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;하나의 노드에 저장할 수 있는 샤드의 개수는 가용한 힙의 크기와 비례 하지만 Elasticsearch에서 그 크기를 제한하고 있지는 않다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* Elasticsearch 공식 블로그에서 제시한 샤드의 개수는 힙 1GB당 20개 미만이다. ( 30GB -&amp;gt; 최대 600 샤드)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사용환경을 고려해본다면 색인량도 작고, 크론탭도 5분마다 실행되므로 부담가는 프로세스는 아니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2년치 데이터를 색인해 보았을 때 샤드당(pri, rep) 6GB를 사용하므로 샤드 구성을 1:1(pri, rep), 속도를 조금 더 생각한다면 2:1 정도를 생각하고 있다. (물론 이상적인 수치가 아니라 개인적인 의견입니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;u&gt;혹시나 헷갈리실까봐 적습니다..!&lt;/u&gt;&lt;br /&gt;프라이머리 샤드 2개, 레플리카 샤드 1개가 있다고 가정한다면 총 샤드 수는 4개입니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹 속도 개선을 위해 샤드 수 변경 요청이 오거나 적정 샤드 크기를 넘어선다면 (20GB)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추후 alias 설정과 ILM을 통해 새로운 인덱스를 만들어 묶어주기로 했다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;u&gt;&lt;i&gt;&lt;b&gt;참고&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;br /&gt;&lt;b&gt;공식 사이트&lt;/b&gt; :&amp;nbsp;https://www.elastic.co/guide/en/elasticsearch/refzerence/current/size-your-shards.html&lt;br /&gt;&lt;b&gt;블로그&lt;/b&gt; :&amp;nbsp;https://www.elastic.co/kr/blog/how-many-shards-should-i-have-in-my-elasticsearch-cluster&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Elasticsearch</category>
      <category>data</category>
      <category>elastic</category>
      <category>Elasticsearch</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/22</guid>
      <comments>https://baektothefuture.tistory.com/22#entry22comment</comments>
      <pubDate>Sat, 22 Mar 2025 02:04:09 +0900</pubDate>
    </item>
    <item>
      <title>병렬 프로세스 최적화_CompletableFuture</title>
      <link>https://baektothefuture.tistory.com/21</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;저희 회사는 SNS 데이터를 다룹니다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터의 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;제목, 내용 &lt;/span&gt;길이가 매우 짧은 것부터 긴 것까지 다양한 형태의 데이터들을 처리하고 관리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재색인 프로세스를 Airflow에 적용하기 위한 검토 과정에서 문제점을 발견하여 최적화를 진행해 보았는데요..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나름 성공적인 결과를 낸 것 같아 최적화 과정을 공유해드리려고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 프로세스는 Elasticsearch에서 데이터를 가져와 해당 문서를 분석하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 Elasticsearch로 재색인 하는 과정을 진행하고 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 중 시간이 가장 오래걸리는 텍스트 분석 과정에서 병렬처리를 하고 있는데요! 코드는 아래와 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;기존 병렬 프로세스 코드&lt;/h4&gt;
&lt;pre id=&quot;code_1736572452650&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CompletableFuture&amp;lt;List&amp;lt;RDataResultDTO&amp;gt;&amp;gt; analysisDataFuture = CompletableFuture.supplyAsync(() -&amp;gt;
			dataList.parallelStream()
      // 연관어 + 감성어
      .map(data -&amp;gt; dao.getAnalyzedRDataDTO(data, searchDate))
      .collect(Collectors.toList())
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;time : 43~46 sec&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;개선방안&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무작위로 들어오는 텍스트 길이(분석 대상)를 고려할 때, work stealing으로 인한 빈번한 Context Switching이 단일 스레드보다 성능이 저하되지는 않을지, 또는 스레드 수를 고정하는 것이 더 효율적일지에 대해 테스트를 진행했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분석 결과, I/O 집중 작업보다 CPU 집중 작업의 비중이 높다는 것을 확인했으며, 스레드 풀을 미리 생성하여 고정된 스레드로 처리했을 때 성능이 향상되는 것을 검증했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 모니터링을 보며 의아했던 점은 &lt;b&gt;worker Thread Running time&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;ddd (1).png&quot; data-origin-width=&quot;1046&quot; data-origin-height=&quot;486&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckd4XH/btsLK1rF3il/pUgF4mUU1ZlG7GWOAj4Ebk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckd4XH/btsLK1rF3il/pUgF4mUU1ZlG7GWOAj4Ebk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckd4XH/btsLK1rF3il/pUgF4mUU1ZlG7GWOAj4Ebk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fckd4XH%2FbtsLK1rF3il%2FpUgF4mUU1ZlG7GWOAj4Ebk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1046&quot; height=&quot;486&quot; data-filename=&quot;ddd (1).png&quot; data-origin-width=&quot;1046&quot; data-origin-height=&quot;486&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Worker Thread 실행 시간 : 전체 실행 시간의 약 23%&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 모니터링을 보고 느낀점은 &quot;일 편하게 하네?&quot; 였습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재는 분석 단계에서만 병렬 프로세스를 활용하고 있습니다. 하지만 병렬 작업을 분석에서 색인 과정까지 확대하면 처리 속도를 개선하고 CPU를 더욱 효율적으로 사용할 수 있을 것으로 판단했습니다. CPU 사용률과 메모리 활용도가 높지 않은 상태였기에, 시스템에 추가 부하를 주어도 충분히 감당할 수 있을 것으로 보였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;변경사항&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리팩토링 (메서드 세분화)&lt;/li&gt;
&lt;li&gt;CompletableFuture의 thenAccept를 활용한 비동기작업 동기처리&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1736576509090&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;CompletableFuture&amp;lt;Void&amp;gt;&amp;gt; futuresList = new ArrayList&amp;lt;&amp;gt;();
while (check.get()) {
	List&amp;lt;RDataResultDTO&amp;gt; docs = getDocument(searchDate, instance, distribute);
    if(docs.isEmpty()) {
    	break;
    }
    int size = docs.size();
    lastSeq = docs.get(size - 1).getLo_seq_org();
    CompletableFuture&amp;lt;Void&amp;gt; pipeline = CompletableFuture.supplyAsync(() -&amp;gt; doAnalysis(docs),forkJoinPool)
    	.thenAccept(this::postAnalyzedData);
    futuresList.add(pipeline); // 모든 작업을 리스트에 저장
}

// 모든 CompletableFuture 작업이 완료될 때까지 대기
CompletableFuture.allOf(futuresList.toArray(new CompletableFuture[0])).join();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;테스트 결과&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;기존 대비 65% 속도 향상&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리팩토링 후 적용된 병렬처리 방식으로 처리 속도가 기존 40초대에서 16초로 65% 향상되었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1039&quot; data-origin-height=&quot;528&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WAGli/btsLKMIe2Ki/83VHmr2cPThpnf83qKkAnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WAGli/btsLKMIe2Ki/83VHmr2cPThpnf83qKkAnk/img.png&quot; data-alt=&quot;열심히 일하는 스레드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WAGli/btsLKMIe2Ki/83VHmr2cPThpnf83qKkAnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWAGli%2FbtsLKMIe2Ki%2F83VHmr2cPThpnf83qKkAnk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1039&quot; height=&quot;528&quot; data-origin-width=&quot;1039&quot; data-origin-height=&quot;528&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;열심히 일하는 스레드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 이 방식은 모든 task를 작업 Queue에 넣고 시작하기에 시스템 부하를 고려한 코드 설계가 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;텍스트 길이가 5000자에서 9000자인 21,220개의 문서를 34분간 색인해 보았을때&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;258&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkKQYG/btsLJN2gOVU/f51oLnQg2Jlmormz6FFuD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkKQYG/btsLJN2gOVU/f51oLnQg2Jlmormz6FFuD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkKQYG/btsLJN2gOVU/f51oLnQg2Jlmormz6FFuD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkKQYG%2FbtsLJN2gOVU%2Ff51oLnQg2Jlmormz6FFuD0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1034&quot; height=&quot;258&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;258&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;힙 메모리가 지속적으로 증가하는 현상을 확인했으며, 최종적으로 메모리가 감소하긴 했으나 이를 안정적으로 관리하기 위한 코드 개선이 필요했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;추가된 코드&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1736576809237&quot; class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;
// 가용 프로세서 확인
int processors = Runtime.getRuntime().availableProcessors()-2;
System.out.println(&quot;Processor : &quot; + processors);
// 작업 예정 Task 수 관리 변수
int getQueuedTaskCount = processors*2; 

while (check.get()) {
	// 기존 코드
	...
    // 추가
    if (futuresList.size() &amp;gt;= 50) { ///  task를 비워줌으로써 heap을 살짝 덜먹음
        CompletableFuture&amp;lt;Void&amp;gt; allFutures = CompletableFuture.allOf(futuresList.toArray(new CompletableFuture[0]));
        allFutures.join();
        futuresList.clear();
    }
}
if (!futuresList.isEmpty()) {
    CompletableFuture&amp;lt;Void&amp;gt; allRemainingFutures = CompletableFuture.allOf(futuresList.toArray(new CompletableFuture[0]));
    allRemainingFutures.join();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;CPU와 메모리 사용률을 조정 후 테스트 결과 (최종)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;nbsp;왼쪽&amp;nbsp;(오리지널)&amp;nbsp;&amp;nbsp;:&amp;nbsp;Uptime:&amp;nbsp;6&amp;nbsp;min&amp;nbsp;15&amp;nbsp;sec&amp;nbsp;/&amp;nbsp;Heap&amp;nbsp;Size:&amp;nbsp;3,302,490,112B&lt;br /&gt;-&amp;nbsp;오른쪽&amp;nbsp;(튜닝)&amp;nbsp;:&amp;nbsp;Uptime:&amp;nbsp;4&amp;nbsp;min&amp;nbsp;38&amp;nbsp;sec&amp;nbsp;/&amp;nbsp;Heap&amp;nbsp;Size:&amp;nbsp;3,615,490,048B&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1045&quot; data-origin-height=&quot;558&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brdFIz/btsLKEQ52UN/TgB3cUMEhqsX1upzC5byzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brdFIz/btsLKEQ52UN/TgB3cUMEhqsX1upzC5byzK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brdFIz/btsLKEQ52UN/TgB3cUMEhqsX1upzC5byzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrdFIz%2FbtsLKEQ52UN%2FTgB3cUMEhqsX1upzC5byzK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1045&quot; height=&quot;558&quot; data-origin-width=&quot;1045&quot; data-origin-height=&quot;558&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 부하를 고려하지 않았을 때는 초반 Used Heap 사이즈가 3GB를 가볍게 넘었었지만 작업량 관리 코드를 추가함으로써 개선된 모습을 볼 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지는 현재 환경에 바로 적용할 수 있도록 설계를 하여 최적화를 진행했지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 도입될 Airflow, Kubernetes 환경을 감안하면 외부 Queue를 활용하여 확장성과 운용성을 높일 수 있는 설계도 고려해 보면 좋을것 같습니다..!&lt;/p&gt;</description>
      <category>Java</category>
      <category>CompletableFuture</category>
      <category>java</category>
      <category>병렬처리</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/21</guid>
      <comments>https://baektothefuture.tistory.com/21#entry21comment</comments>
      <pubDate>Sat, 11 Jan 2025 15:58:15 +0900</pubDate>
    </item>
    <item>
      <title>Curator를 활용한 Snapshot 테스트</title>
      <link>https://baektothefuture.tistory.com/20</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;데이터 생애주기를 관리하기 위하여 Curator을 활용한 Bash Script를 구성해보았습니다..!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;현재 Crontab으로 하루에 한번 운용되고 있으며 아래와 같은 순서로 동작이 구성되었습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;동작 순서&lt;/b&gt;&lt;br /&gt;1.&amp;nbsp;allocation&amp;nbsp;:&amp;nbsp;hot&amp;nbsp;&amp;rarr;&amp;nbsp;warm&amp;nbsp;&lt;br /&gt;2.&amp;nbsp;snapshot&amp;nbsp;:&amp;nbsp;사용자&amp;nbsp;인덱스만&amp;nbsp;snapshot&amp;nbsp;생성&lt;br /&gt;3. delete_indices : snapshot이 완료된 인덱스 삭제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1736337253136&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#!/bin/bash

snapshot_date=$(date -d '7 days ago' +%Y%m%d)
snapshot_name=&quot;lucy_main_bac1_${snapshot_date}_snapshot&quot;

cat &amp;lt;&amp;lt; EOF &amp;gt; action_file.yml
actions:
  1:
    action: allocation
    description: &quot;apply shard allocation&quot;
    options:
      key: tier
      value: warm
      wait_for_completion: True
      allocation_type: require
    filters:
      - filtertype: pattern
        kind: prefix
        value: 'lucy_main_bac1_'
      - filtertype: age
        source: name
        timestring: '%Y%m%d'
        unit: days
        unit_count: 3
        direction: older
  2:
    action: snapshot
    description: &quot;Snapshot&quot;
    options:
      repository: backup
      name: ${snapshot_name}
      wait_for_completion: True
      max_wait: 3000
      include_global_state: False
      ignore_unavailable: False
      wait_interval: 5
    filters:
      - filtertype: pattern
        kind: prefix
        value: 'main_target_'
      - filtertype: age
        source: name
        timestring: '%Y%m%d'
        unit: days
        unit_count: 7
        direction: older
  3:
    action: delete_indices
    description: &quot;Delete Selected indices&quot;
    options:
      continue_if_exception: False
    filters:
      - filtertype: pattern
        kind: prefix
        value: 'main_target_'
      - filtertype: age
        source: name
        timestring: '%Y%m%d'
        unit: days
        unit_count: 7
        direction: older
EOF

/usr/local/bin/curator --config /app/curator.yml /app/action_file.yml&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;매일 갱신해야 하기 때문에 동적인 변수 할당을 위해 Script로 작성하여 실행&lt;/u&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;Curator을 통한 Snapshot 결과&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;2025년 1월 1일&lt;br /&gt;목표 인덱스 : main_target_20250101&lt;br /&gt;데이터량 : 약 400만건&lt;br /&gt;걸린 시간 : 8 min&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;2025년 1월 2일&lt;br /&gt;목표 인덱스&amp;nbsp; : main_target_20250102&lt;br /&gt;데이터량 : 약 400만건 (4,002,556)&lt;br /&gt;걸린 시간 : 8 min&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;/p&gt;</description>
      <category>Elasticsearch</category>
      <category>bash</category>
      <category>curator</category>
      <category>Elasticsearch</category>
      <category>script</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/20</guid>
      <comments>https://baektothefuture.tistory.com/20#entry20comment</comments>
      <pubDate>Wed, 8 Jan 2025 21:01:30 +0900</pubDate>
    </item>
    <item>
      <title>Docker Hub를 Helm Charts 저장소로</title>
      <link>https://baektothefuture.tistory.com/19</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;사이드 프로젝트를 Helm Charts로 배포하려고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해 Helm Charts를 저장할 저장소를 선택해야 하는데,, 현 직장에서는 Harbor을 쓰지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조금 오래된 내 맥북에서 개발 환경을 구성한다고 생각하니 용량이 아까워,,ㅎ 외부 레지스트리를 이용하려고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;s&gt;Helm Charts 설치는 되어있다고 가정햐겠습니다.&lt;/s&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;먼저 터미널(iterm, wsl)에 접속해 docker에 로그인 해줍니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;docker login -u &amp;lt;id&amp;gt; -p &amp;lt;password&amp;gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1066&quot; data-origin-height=&quot;72&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZ7PPS/btsLGlXsnx6/LYSaA3BL3wK0TBPxWvYm21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZ7PPS/btsLGlXsnx6/LYSaA3BL3wK0TBPxWvYm21/img.png&quot; data-alt=&quot;비밀번호를 바로 쓰지 말라네요,,ㅎ 로그인 성공&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZ7PPS/btsLGlXsnx6/LYSaA3BL3wK0TBPxWvYm21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZ7PPS%2FbtsLGlXsnx6%2FLYSaA3BL3wK0TBPxWvYm21%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1066&quot; height=&quot;72&quot; data-origin-width=&quot;1066&quot; data-origin-height=&quot;72&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;비밀번호를 바로 쓰지 말라네요,,ㅎ 로그인 성공&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그 다음 Docker Hub에 올릴 Helm Chart를 만듭니다. (예시용)&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;helm create &amp;lt;example_이름&amp;gt;&amp;nbsp;&lt;/blockquote&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;다운로드를 하셨다면 아래와 같은 구조의 폴더가 생성 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1736156676702&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;demo % tree             
.
├── Chart.yaml
├── charts
├── templates
│   ├── NOTES.txt
│   ├── _helpers.tpl
│   ├── deployment.yaml
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── service.yaml
│   ├── serviceaccount.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml

3 directories, 10 files&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;완성 되었다면..! helm package 명령어를 통해 .tgz 파일로 패키지화 시켜줍니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;helm package &amp;lt;example_이름&amp;gt;&amp;nbsp;&lt;/blockquote&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 Docker Hub에 release 하도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;helm push example-0.1.0.tgz oci://registry-1.docker.io/&amp;lt;docker id&amp;gt;&amp;nbsp;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;68&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5WXKB/btsLFxdgHEp/siw3uwcNENtfV9Tgym1GGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5WXKB/btsLFxdgHEp/siw3uwcNENtfV9Tgym1GGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5WXKB/btsLFxdgHEp/siw3uwcNENtfV9Tgym1GGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5WXKB%2FbtsLFxdgHEp%2Fsiw3uwcNENtfV9Tgym1GGk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1138&quot; height=&quot;68&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;68&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Docker Hub에 들어가 확인해보시면 잘 저장되어 있는걸 확인할 수 있습니다..!&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;1011&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wqDUX/btsLFMON0Tt/kqKHoriyEMws2POUtW6nH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wqDUX/btsLFMON0Tt/kqKHoriyEMws2POUtW6nH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wqDUX/btsLFMON0Tt/kqKHoriyEMws2POUtW6nH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwqDUX%2FbtsLFMON0Tt%2FkqKHoriyEMws2POUtW6nH1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3000&quot; height=&quot;1011&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;1011&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>쿠버네티스/helm</category>
      <category>docker</category>
      <category>docker hub</category>
      <category>helm</category>
      <category>helm charts</category>
      <category>repository</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/19</guid>
      <comments>https://baektothefuture.tistory.com/19#entry19comment</comments>
      <pubDate>Mon, 6 Jan 2025 18:56:26 +0900</pubDate>
    </item>
    <item>
      <title>Helm Chart 개념 정리</title>
      <link>https://baektothefuture.tistory.com/18</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;까먹지 않기 위해 정리하는 글 입니다..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;헬름이란?&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠버네티스에 패키지를 손수비게 배포할 수 있도록 패키지를 관리하는 쿠버네티스 전용 패키지 매니저&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;패키지&lt;/b&gt; : 실행 파일뿐만 아니라 실행 환경에 필요한 의존성 파일과 환경 정보들의 묶음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;패키지 매니저&lt;/b&gt; : 외부에 있는 저장소에서 패키지 정보를 받아와 패키지를 안정적으로 관리하는 도구 (저장소 아님)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 더 이해하기 쉽게 다른 예시를 아래와 같이 정리해보았습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;플랫폼&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;패키지 매니저&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;저장소&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;사용 목적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;리눅스&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;yum, apt&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;배포판 저장소&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;소프트웨어 의존성 관리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;파이썬&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;pip&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;pypi.org&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;파이썬 모듈 의존성 관리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;자바&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;maven&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;maven repository&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;자바 라이브러리 의존성 관리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;쿠버네티스&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;helm&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;artifacthub.io&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;쿠버네티스 패키지 관리&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;패키지 매니저의 역할&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;패키지 관리&lt;/li&gt;
&lt;li&gt;패키지 의존성 관리&lt;/li&gt;
&lt;li&gt;패키지 보안 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;왜 쓸까?&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;문제상황&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;다수의 오브젝트를 배포하는 yaml 파일은 '---' 인 파일 구분자로 묶어 여러 오브젝트를 단일 야믈로 배포할 수 있습니다.&amp;nbsp;&lt;br /&gt;하지만 이런 경우 변경 사항을 추적할 때 모든 내용이 한 야믈 파일에 담겨 있기 때문에 혼선을 줄 수 있습니다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;이를 해결하려면 목적에 맞게 디렉터리를 만들고 야믈 파일을 분리해 관리하면서 배포 시에는 디렉터리를 kubectl apply -f의 인자로 넘겨&lt;br /&gt;줘야 합니다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;하지만..! 이런 방식을 사용한다면 요구 조건에 변경되는 야믈 파일을 매번 개별 디렉터리에 작성해야 하고 디렉터리가 늘어날수록 관리 포인트도 늘어나게 됩니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;헬름을 사용한 해결&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;헬름을 사용하면 요구 조건별로 리소스를 편집하거나 변수를 넘겨서 처리하는 패키지를 만들 수 있습니다.&amp;nbsp;&lt;br /&gt;다양한 요구 조건을 처리할 수 있는 패키지를 차트(Chart)라고 하는데, 이름 헬름 저장소에 공개해 여러 사용자와 공유합니다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;헬름의 전반적인 흐름&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;헬름.png&quot; data-origin-width=&quot;1372&quot; data-origin-height=&quot;774&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yV9lh/btsLC154C72/VbmDF9wKohzHPeY1Tbmkk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yV9lh/btsLC154C72/VbmDF9wKohzHPeY1Tbmkk0/img.png&quot; data-alt=&quot;누군가 책에서 따온걸 내가 다시 따온..&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yV9lh/btsLC154C72/VbmDF9wKohzHPeY1Tbmkk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyV9lh%2FbtsLC154C72%2FVbmDF9wKohzHPeY1Tbmkk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1372&quot; height=&quot;774&quot; data-filename=&quot;헬름.png&quot; data-origin-width=&quot;1372&quot; data-origin-height=&quot;774&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;누군가 책에서 따온걸 내가 다시 따온..&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아티팩트허브 영역은 저장소 영역이라고 보면 될 것 같습니다..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;helm chart의 저장소는 여러가지가 있는데 저희 회사의 경우 &lt;b&gt;Harbor&lt;/b&gt;을 주로 쓰는 편입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;생산자 영역&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업자가 helm 명령으로 작업 공간을 생성하면 templates 디렉터리로 애플리케이션 배포에 필요한 여러 야믈 파일과 구성 파일을 작성할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;values.yaml : 조건별 분기, 값 전달, 기본값 처리 등&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Charts.yaml : 차트의 이름, 목적, 배포되는 애플리케이션 버전 정보 등&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;저장소 영역&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 찾고자 하는 애플리케이션 패키지를 검색하여 저장된 주소를 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사용자 영역&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션의 차트 저장소 주소를 저장소에서 얻으면 헬름을 통해서 주소를 등록 및 설치(릴리스)&lt;/p&gt;</description>
      <category>쿠버네티스/helm</category>
      <category>ci/cd</category>
      <category>helm</category>
      <category>kubernets</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/18</guid>
      <comments>https://baektothefuture.tistory.com/18#entry18comment</comments>
      <pubDate>Tue, 31 Dec 2024 16:16:56 +0900</pubDate>
    </item>
    <item>
      <title>NiFi 성능 최적화 테스트_스레드 개수와 Concurrent Tasks 상관관계</title>
      <link>https://baektothefuture.tistory.com/17</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 NiFi 테스트를 해보며 얻었던 인사이트들을 여러분들께 공유하려고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;(조회수는 적지만)&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;스레드 생성 개수와 Concurrent Tasks 상관관계 찾기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 테스트는 Java 스레드 풀을 통한 스레드 생성 개수와 NiFi에서 관리하는 스레드 개수(Concurrent Tasks)를 조정하여 최적의 관계를 찾아볼 예정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;최적화 대상&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;ExecuteStreamCommand 프로세서 : Elasticsearch에 색인하는 Jar 파일&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;env.&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;- 3 node cluster&lt;br /&gt;- core : 40/40/32&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;알아두기&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;전체 메뉴인 (우상단의 햄버거 아이콘)을 클릭하여 노드 당 할당할 수 있는 Concurrent Tasks의 최대 개수를 설정해야합니다.&lt;br /&gt;개수를 늘릴 때는 클러스터를 재시작할 필요가 없지만, 이를 줄이게 된다면 클러스터를 재시작할 필요가 있습니다!&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Test&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;1.&amp;nbsp;스레드&amp;nbsp;생성&amp;nbsp;개수&amp;nbsp;(10)&amp;nbsp;:&amp;nbsp;Concurrent&amp;nbsp;Tasks&amp;nbsp;(10)&lt;br /&gt;2.&amp;nbsp;스레드&amp;nbsp;생성&amp;nbsp;개수&amp;nbsp;(10)&amp;nbsp;:&amp;nbsp;Concurrent&amp;nbsp;Tasks&amp;nbsp;(20)&lt;br /&gt;3.&amp;nbsp;스레드&amp;nbsp;생성&amp;nbsp;개수&amp;nbsp;(20)&amp;nbsp;:&amp;nbsp;Concurrent&amp;nbsp;Tasks&amp;nbsp;(20)&lt;br /&gt;4. 스레드 생성 개수 (30) : Concurrent Tasks (30)&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;ExecuteStreamCommand Status History&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(차례대로 1, 2, 3, 4번 테스트)&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;ddddd.png&quot; data-origin-width=&quot;593&quot; data-origin-height=&quot;372&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rBvZf/btsLaDed3jI/EIkOyeaAlqMsiUIMj9eCTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rBvZf/btsLaDed3jI/EIkOyeaAlqMsiUIMj9eCTk/img.png&quot; data-alt=&quot;Bytes Read (5 mins)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rBvZf/btsLaDed3jI/EIkOyeaAlqMsiUIMj9eCTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrBvZf%2FbtsLaDed3jI%2FEIkOyeaAlqMsiUIMj9eCTk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;593&quot; height=&quot;372&quot; data-filename=&quot;ddddd.png&quot; data-origin-width=&quot;593&quot; data-origin-height=&quot;372&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Bytes Read (5 mins)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;&lt;b&gt;CPU 사용률&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;913&quot; data-origin-height=&quot;371&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qIrRs/btsK3kUd6yf/6e1mDwTj1AXHlBSRedxivk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qIrRs/btsK3kUd6yf/6e1mDwTj1AXHlBSRedxivk/img.png&quot; data-alt=&quot;CPU 사용률 From Prometheus&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qIrRs/btsK3kUd6yf/6e1mDwTj1AXHlBSRedxivk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqIrRs%2FbtsK3kUd6yf%2F6e1mDwTj1AXHlBSRedxivk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;913&quot; height=&quot;371&quot; data-origin-width=&quot;913&quot; data-origin-height=&quot;371&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;CPU 사용률 From Prometheus&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;u&gt;첫번째와 두번째 그래프의 cpu사용량이 같은것으로 보아 Java에서 발생된 스레드의 수는 concurrent tasks 설정에 의해 제한을 받는다는것을 알 수 있습니다.&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Number of time driven Threads&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;dddd.png&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;707&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zn5zY/btsLayD7auQ/oAlVsJ48ygDREXHKIK4g2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zn5zY/btsLayD7auQ/oAlVsJ48ygDREXHKIK4g2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zn5zY/btsLayD7auQ/oAlVsJ48ygDREXHKIK4g2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzn5zY%2FbtsLayD7auQ%2FoAlVsJ48ygDREXHKIK4g2k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;997&quot; height=&quot;707&quot; data-filename=&quot;dddd.png&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;707&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;u&gt;파란색 그래프는 NiFi를 통해 돌아가는 모든 스레드의 개수를 나타낸다. -&amp;gt; 노랑, 빨강, 초록을 합친값의 + 1(NiFi 스레드)&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;u&gt;스레드 증가율을 확인해보면 그래프는 CPU 사용량과 비례하여 증가하는 형태를 띄우는걸 확인할 수 있습니다.&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;이번 테스트를 통해 알게된 점은 이와 같습니다.&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스레드 생성 개수는 Concurrent tasks 설정값을 넘지 못합니다. -&amp;gt; CPU 점유율이 비슷함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 가용한 모든 스레드가 올라가고 일정시간이 지난 후 (빠른 비교를 위해 searchElasticsearch 프로세서의 Schedule Duration을 1 sec로 하였습니다.) Queue에 남아있는 FlowFile을 탐색해 봤을 시 스레드를 코어 수 이상 늘린다고 더 좋은 효율을 내진 않습니다 (큐에 남아있는 FlowFile 수를 비교)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 결과를 통해 추측해 볼 수 있는 결과는 스레드 수 : Concurrent tasks 수가 1대1일 때 적합하다고  예상하지만...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;저의 경우 긴 시간 측정해보지 않았기에 정확한 값은 아니라고 생각합니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 더 지켜봐야할 점이 있다고 생각합니다. 두가지 관점으로 생각해보자면 코드, 스레드 생애주기 관점입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;코드 관점&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;실행시킬 코드를 확인해보면 ForkJoinPool을 통해 스레드간 간섭을 허용하여 테스크를 처리하고 있지만 이는 길이가 100인 JSONArray를 처리하고 있으므로 오히려 컨택스트 스위칭이 빈번해져 부하가 더 클 수 있다고 생각합니다. (어떤 데이터를 처리하고 있는지에 따라 다름) 따라서 인입 데이터의 유형에 맞춘 병렬 처리를 좀 더 고려해보는것이 좋을 것 같다고 생각합니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;스레드 생애주기&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Concurrent Threads 개수가 사용 가능한 스레드 수의 배수가 되는것이 1:1 관계보다 더 최적화된 설정일 가능성이 있습니다.&lt;br /&gt;위의 측정한 그래프 중 Number of time driven Threads의 Status History를 보면 스레드 개수보다 ConcurrentTasks가 조금 더 높은것을 확인할 수 있는데 조금 더 오래 돌려본다면 1:1 관계보다 좋은 결과가 나올 가능성이 있습니다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;특이사항&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fafafa; color: #333333; text-align: start;&quot;&gt;테스트 진행 후 아래와 같은 작업을 진행했었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 불필요한 프로세서 정리&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(실행대상이 아닌 프로세서 포함)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 클러스터 재시작&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 동일조건 하 CPU 점유율이 상당히 줄은 경험이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹 NiFi를 통해 작업을 하실 경우 불필요한 프로세서는 정리하는 것을 추천드립니다..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>NiFi</category>
      <category>NiFi</category>
      <category>나이파이</category>
      <category>데이터파이프라인</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/17</guid>
      <comments>https://baektothefuture.tistory.com/17#entry17comment</comments>
      <pubDate>Fri, 6 Dec 2024 21:18:58 +0900</pubDate>
    </item>
    <item>
      <title>NiFi Index to Index Data Pipeline</title>
      <link>https://baektothefuture.tistory.com/16</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 Nifi 데이터 파이프라인을 소개하려고 합니다!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NiFi는 Attribute, Content로 이루어진 FlowFile을 활용하며, 직관적으로 파악할 수 있는 UI 제공과 코드 없이도 기존 프로세서를 사용하여 데이터 파이프라인을 개발할 수 있습니다. (기존 프로세서 외에도 Jar, Nar 파일을 프로세서로 실행시킬 수도 있습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;제가 소개할 NiFi를 통한 목표는 아래와 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;목표&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;인덱스 to 인덱스 데이터 색인 (Reindex 과정)&lt;br /&gt;- search_after 사용&lt;br /&gt;- Bulk API 사용&lt;br /&gt;&lt;u&gt;&lt;b&gt;제약사항&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;- Query를 날릴 수 있어야 함&lt;br /&gt;- 중복 불가&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;구성 환경&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;NiFi 1.27.0&lt;/li&gt;
&lt;li&gt;Linux Centos&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;필자의 경우 해당 프로세스를 사용하기 전에 SSL 설정, Key를 발급받아 Variables에 저장해둔 상태입니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Datapipe line&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구성된 파이프라인의 일부인 SearchElasticsearch -&amp;gt; Update Attribute -&amp;gt; SplitJson 부분을 먼저 보겠습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;SearchElasticsearch &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(시작)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; -&amp;gt; Update Attribute -&amp;gt; SplitJson&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;1040&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3tw8n/btsKREKgp2b/ErMgWB3PG1oi9XrLNyokp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3tw8n/btsKREKgp2b/ErMgWB3PG1oi9XrLNyokp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3tw8n/btsKREKgp2b/ErMgWB3PG1oi9XrLNyokp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3tw8n%2FbtsKREKgp2b%2FErMgWB3PG1oi9XrLNyokp1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;306&quot; height=&quot;530&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;1040&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;SearchElasticsearch 특징&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;[] JSONArray 형태로 인입&lt;/li&gt;
&lt;li&gt;Lucene Syntax 쿼리(ex. query_string)는 지원하지 않는다. (DSL 쿼리를 활용해야 함)&lt;/li&gt;
&lt;li&gt;Paging 처리를 할 때 (search_after, ..) 모든 document를 돌았음에도 중지되지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 SearchElasticsearch Processor의 특징 때문에 Update Attribute, SplitJson을 추가로 해주어 데이터를 처리합니다.&lt;i&gt;&lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;i&gt;UpdateAttribute&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;Update Attribute 프로세서에서는 SearchElasticsearch로 들어온 JSONArray의 길이를 Attribute에 추가해줍니다.&lt;/u&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;'+' 눌러 속성추가 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;${hit.count:gt(0):and(${hit.count:equals(${size})})}&amp;nbsp;&lt;br /&gt;(여기서 size 는 해당 프로세서 그룹의 variables에 적용해둔 search_after을 페이징 사이즈입니다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;SplitJson&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;SplitJson 프로세서에서는 []로 들어온 JSONArray를 JSONObjecty 단위로 분할해 줍니다.&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;b&gt;(이어서) EvaluateJsonPath -&amp;gt; RouteOnAttribute -&amp;gt; PutElasticsearchJson&lt;/b&gt;&lt;br /&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7nsGX/btsKPxeV9uN/DjZ7zEMIYPHQi8m5XdWtdk/img.png&quot; data-origin-width=&quot;1670&quot; data-origin-height=&quot;744&quot; data-is-animation=&quot;false&quot; /&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;i&gt;EvaluateJsonPath&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EvaluateJsonPath 프로세서에서는 JSONObject로 쪼개진 FlowFile을 중복 처리를 하기 위해 속성을 추가해줍니다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;'+' 눌러 속성추가 :&lt;span&gt; 해당 FlowFile Content 부분에서 Bulk API의 _id로 쓸 고유값을 가져옵니다.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;$.kw_docid ('$'는 원문을 뜻함)&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;RouteOnAttribute&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;RouteOnAttribute 프로세서를 통해 &quot;&lt;b&gt;&lt;i&gt;UpdateAttribute&lt;/i&gt;&lt;/b&gt;&quot; 프로세서에서 설정한 속성값에 따라 분기 처리를 해줍니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;PutElasticsearch&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 프로세서를 통해 Bulk API를 날려줍니다. bulk size를 지정할 수 있으며 Identifier Attribute 설정을 통해&lt;br /&gt;&quot;&lt;b&gt;&lt;i&gt;EvaluateJsonPath&lt;/i&gt;&lt;/b&gt;&quot;에서 설정한 bulk api의 _id를 지정해줍니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;* 주의 사항 *&amp;nbsp;&lt;br /&gt;필자는 해당 프로세스를 설정할 때 설정한 _id값이 아닌 랜던값이 설정되었는데요..&lt;br /&gt;당시 속성 이름을 언더바가 포함된 &quot;_id&quot;로 설정했으며 언더바를 지우니 해결되었습니다.&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;저의 경우 데이터 색인작업이 끝나면 &quot;&lt;b&gt;&lt;i&gt;InvokeHttp&lt;/i&gt;&lt;/b&gt;&quot; 프로세서를 통해 해당 데이터 파이프라인(프로세서 그룹)을 정지 시켰습니다.&lt;br /&gt;NiFi의 설정이나 다른 부분들을 자세하게 다루진 않았습니다..만 혹시 InvokeHttp를 적용하고 싶으시거나 막히는 부분이 있으시다면 댓글 남겨주세요! 추후에 글을 작성할수도 있지만 댓글달아주시면 바로바로 답변드리겠습니다!&lt;/p&gt;</description>
      <category>NiFi</category>
      <category>data</category>
      <category>Elasticsearch</category>
      <category>NiFi</category>
      <category>Pipeline</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/16</guid>
      <comments>https://baektothefuture.tistory.com/16#entry16comment</comments>
      <pubDate>Wed, 20 Nov 2024 21:12:43 +0900</pubDate>
    </item>
    <item>
      <title>CompletableFuture 테스트</title>
      <link>https://baektothefuture.tistory.com/15</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://baektothefuture.tistory.com/13&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://baektothefuture.tistory.com/13&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1729934946569&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Java - 병렬처리 (Future 인터페이스 활용)&quot; data-og-description=&quot;90만건 가까이 되는 데이터를 Elasticsearch에서 읽어 전처리 후 다시 Elasticsearch에 색인했었습니다.이 과정에서 약 3~4시간정도 소요가 되는데 이를 어떻게하면 빠르게 처리할 수 있을까 고민하다가 &quot; data-og-host=&quot;baektothefuture.tistory.com&quot; data-og-source-url=&quot;https://baektothefuture.tistory.com/13&quot; data-og-url=&quot;https://baektothefuture.tistory.com/13&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/nEUaW/hyXlSEan3e/6adtJJ1GkkMt5Tg4kxjZEk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/M4uLc/hyXlMDXmlI/v2iLpj8jCnfhhrCJir06hK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://baektothefuture.tistory.com/13&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://baektothefuture.tistory.com/13&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/nEUaW/hyXlSEan3e/6adtJJ1GkkMt5Tg4kxjZEk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/M4uLc/hyXlMDXmlI/v2iLpj8jCnfhhrCJir06hK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Java - 병렬처리 (Future 인터페이스 활용)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;90만건 가까이 되는 데이터를 Elasticsearch에서 읽어 전처리 후 다시 Elasticsearch에 색인했었습니다.이 과정에서 약 3~4시간정도 소요가 되는데 이를 어떻게하면 빠르게 처리할 수 있을까 고민하다가&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;baektothefuture.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;이전글에서는 Future 인터페이스에 다루어 보았는데요 이번에는 CompletableFuture에 대해 알아보도록 하겠습니다.&lt;br /&gt;&lt;br /&gt;Future vs CompletableFuture&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;출처 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://11st-tech.github.io/2024/01/04/completablefuture/&quot;&gt;https://11st-tech.github.io/2024/01/04/completablefuture/&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 91px;&quot; border=&quot;1&quot; data-ke-style=&quot;style12&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;Future&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;CompletableFuture&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;Blocking&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;non-blocking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;여러 연산을 함께 연결하기 어려움&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;여러 연산을 함께 연결&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;여러 연산 결과를 결합하기 어려움&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;여러 연산 결과를 결합&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;연산 성공 여부만 확인할 수 있고 예외처리 어려움&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;execeptionally(), handle()을 통한 예외 처리&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 표를 보면 Future 인터페이스의 한계점을 CompletablFuture을 통해 해결한 것을 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주로 활용하는 메서드&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;runAsync()&lt;/b&gt;: 반환값이 없는 비동기 작업을 실행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;supplyAsync()&lt;/b&gt;: 반환값이 있는 비동기 작업을 실행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;thenApply()&lt;/b&gt;: 이전 단계의 결과를 받아서 새로운 값을 반환합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;thenAccept()&lt;/b&gt;: 이전 단계의 결과를 받아서 소비(consumer)합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;thenRun()&lt;/b&gt;: 이전 단계의 결과를 사용하지 않고 후속 작업을 수행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이에 대한 간단한 테스트를 해보았는데 CompletableFuture의 특성을 잘 살린(?) 코드는 아니지만 처음접하는 분들은 예시를 보며 조금이나마 감을 잡았으면 좋겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1729935865062&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package main;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class CompletableFutureExample {
    public static void main(String[] args) {
        List&amp;lt;Integer&amp;gt; job = IntStream.range(1, 11).boxed().collect(Collectors.toList());

        // jobList 생성 및 초기화
        List&amp;lt;List&amp;lt;Integer&amp;gt;&amp;gt; jobList = IntStream.range(1, 101)
                .mapToObj(i -&amp;gt; new ArrayList&amp;lt;&amp;gt;(job)) // 각기 다른 복사본 추가
                .collect(Collectors.toList());

        String version = System.getProperty(&quot;java.version&quot;);
        System.out.println(&quot;JAVA Version : &quot; + version);

        try {
            System.out.println(&quot;=========== multi thread ==============&quot;);
            long start = System.currentTimeMillis();

            // CompletableFuture 리스트 생성
            List&amp;lt;CompletableFuture&amp;lt;List&amp;lt;Integer&amp;gt;&amp;gt;&amp;gt; futureList = new ArrayList&amp;lt;&amp;gt;();

            // 각 job에 대해 비동기 작업 수행
            for (List&amp;lt;Integer&amp;gt; ob : jobList) {
                CompletableFuture&amp;lt;List&amp;lt;Integer&amp;gt;&amp;gt; future = CompletableFuture.supplyAsync(() -&amp;gt; {
                    System.out.println(&quot;현재 스레드 : &quot; + Thread.currentThread().getName());
                    return working(ob);
                }).thenApply(a -&amp;gt; {
                    System.out.println(Thread.currentThread().getName() + &quot; 마지막 단계&quot;);
                    return lastWorking(a);
                });
                futureList.add(future);
            }

            // 모든 작업이 완료될 때까지 대기
            CompletableFuture&amp;lt;Void&amp;gt; combinedFuture = CompletableFuture.allOf(
                    futureList.toArray(new CompletableFuture[0])
            );
            combinedFuture.get(); // 또는 combinedFuture.join();

            long end = System.currentTimeMillis();
            long secDiff = (end - start);

            System.out.println(&quot;parallel : &quot; + secDiff + &quot;ms&quot;);

            // 작업 결과 수집 (필요한 경우)
            /*
            List&amp;lt;List&amp;lt;Integer&amp;gt;&amp;gt; results = futureList.stream()
                    .map(CompletableFuture::join)
                    .collect(Collectors.toList());
            */

            System.out.println(&quot;=========== single thread ==============&quot;);
            long start2 = System.currentTimeMillis();

            for (List&amp;lt;Integer&amp;gt; ob : jobList) {
                lastWorking(working(ob));
            }

            long end2 = System.currentTimeMillis();
            long secDiff2 = (end2 - start2);
            System.out.println(&quot;single thread : &quot; + secDiff2 + &quot;ms&quot;);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static List&amp;lt;Integer&amp;gt; working(List&amp;lt;Integer&amp;gt; list) {
        try {
            Thread.sleep(2000);
            for (int i = 0; i &amp;lt; list.size(); i++) {
                list.set(i, list.get(i) * 10);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return list;
    }

    public static List&amp;lt;Integer&amp;gt; lastWorking(List&amp;lt;Integer&amp;gt; list) {
        try {
            Thread.sleep(2000);
            for (int i = 0; i &amp;lt; list.size(); i++) {
                list.set(i, list.get(i) + 1);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return list;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드의 결과값을 보면 아래와 같습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;..(생략)..&lt;br /&gt;ForkJoinPool.commonPool-worker-10 마지막 단계 ForkJoinPool.commonPool-worker-16 마지막 단계 ForkJoinPool.commonPool-worker-17 마지막 단계 ForkJoinPool.commonPool-worker-4 마지막 단계 &lt;br /&gt;parallel : 24140ms&lt;br /&gt;=========== single thread ============== &lt;br /&gt;single thread : 401558ms &lt;br /&gt;Disconnected from the target VM, address: '127.0.0.1:50706', transport: 'socket' Process finished with exit code 0&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본래는 분석 프로세스를 잘게 나누어 병렬처리를 하려 했지만 사실 컨택스트 스위칭 비용만 늘어나 성능이 더 떨어질 뿐 유의미한 결과를 보지 못했습니다. 병렬프로세스라고 무조건 빠르다고 생각하고 적용하지 말고 프로세스 특성에 맞는지 잘 확인하고 적용하면 좋을것 같습니다...!&lt;/p&gt;</description>
      <category>Java</category>
      <category>CompletableFuture</category>
      <category>Future</category>
      <category>java</category>
      <category>JAVA8</category>
      <category>parallel</category>
      <category>병렬</category>
      <category>병렬처리</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/15</guid>
      <comments>https://baektothefuture.tistory.com/15#entry15comment</comments>
      <pubDate>Sat, 26 Oct 2024 18:52:40 +0900</pubDate>
    </item>
    <item>
      <title>docker-compose.yml 활용하여 Elasticsearch Cluster 만들기</title>
      <link>https://baektothefuture.tistory.com/14</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;동작 테스트를 위해 만들었던 Elasticsearch Cluster docker-compose.yml 파일을 공유하려고 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본래는 보안모드로 구성하려 했으나 빠른 테스트를 위해 보안설정을 하지 않았습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클러스터의 구성은 아래와 같습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;Elasticsearch Cluster&lt;/b&gt;&lt;br /&gt;마스터 노드 : 1개&lt;br /&gt;데이터 노드 : 4개 (node.attr.tier을 통해 노드 구분)&lt;br /&gt;&amp;nbsp; - Hot Node : 3개&lt;br /&gt;&amp;nbsp; - Warm Node : 1개&lt;br /&gt;&lt;b&gt;KIbana&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;++ Hot, Warm 설정은 node.roles 설정이 아닌 node.attr.tier 설정입니다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;docker-compose.yml&lt;/h4&gt;
&lt;pre id=&quot;code_1729856051577&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;version: '3.8'
services:
  # 마스터노드 설정
  master:
    image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
    container_name: master
    environment:
      - node.name=master
      - cluster.name=${CLUSTER_NAME}
      - discovery.seed_hosts=hot01,hot02,hot03,warm
      - cluster.initial_master_nodes=master
      - bootstrap.memory_lock=true
      - xpack.security.enabled=false
      - node.roles=[master]
    ulimits:
      # 메모리 제한 해제 (Elasticsearch) 
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data_master:/usr/share/elasticsearch/data
    # 메모리 제한 설정 (Docker container) : 전체 메모리 사용량 제한
    mem_limit: ${ES_MEM_LIMIT}
    ports:
      - ${ES_PORT}:9200

  hot01:
    depends_on:
      - master
    image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
    container_name: hot01
    environment:
      - node.name=hot01
      - cluster.name=${CLUSTER_NAME}
      - discovery.seed_hosts=master,hot02,hot03,warm
      - cluster.initial_master_nodes=master
      - bootstrap.memory_lock=true
      - xpack.security.enabled=false
      - node.attr.tier=hot
      - node.roles=[data]

    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data_hot01:/usr/share/elasticsearch/data
    mem_limit: ${ES_MEM_LIMIT}
    ports:
      - 9201:9200

  hot02:
    depends_on:
      - master
      - hot01

    image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
    container_name: hot02
    environment:
      - node.name=hot02
      - cluster.name=${CLUSTER_NAME}
      - discovery.seed_hosts=master,hot01,hot03,warm
      - cluster.initial_master_nodes=master
      - bootstrap.memory_lock=true
      - xpack.security.enabled=false
      - node.attr.tier=hot
      - node.roles=[data]      
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data_hot02:/usr/share/elasticsearch/data
    mem_limit: ${ES_MEM_LIMIT}
    ports:
      - 9202:9200

  hot03:
    depends_on:
      - master
      - hot01
      - hot02
      
    image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
    container_name: hot03
    environment:
      - node.name=hot03
      - cluster.name=${CLUSTER_NAME}
      - discovery.seed_hosts=master,hot01,hot02,warm
      - cluster.initial_master_nodes=master
      - bootstrap.memory_lock=true
      - xpack.security.enabled=false
      - node.attr.tier=hot
      - node.roles=[data]      
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data_hot03:/usr/share/elasticsearch/data
    mem_limit: ${ES_MEM_LIMIT}
    ports:
      - 9203:9200

  warm:
    depends_on:
      - master
      - hot01
      - hot02
      - hot03
    
    image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
    container_name: warm
    environment:
      - node.name=warm
      - cluster.name=${CLUSTER_NAME}
      - discovery.seed_hosts=master,hot01,hot02,hot03
      - cluster.initial_master_nodes=master
      - bootstrap.memory_lock=true
      - xpack.security.enabled=false
      - node.attr.tier=warm
      - node.roles=[data]      
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data_warm:/usr/share/elasticsearch/data
    mem_limit: ${ES_MEM_LIMIT}
    ports:
      - 9204:9200

  kibana:
    image: docker.elastic.co/kibana/kibana:${STACK_VERSION}
    container_name: kibana
    ports:
      - ${KIBANA_PORT}:5601
    environment:
      - ELASTICSEARCH_HOSTS=http://master:9200
    mem_limit: ${KB_MEM_LIMIT}
    depends_on:
      - master
      - hot01
      - hot02
      - hot03
      - warm

volumes:
  data_master:
    driver: local
  data_hot01:
    driver: local
  data_hot02:
    driver: local
  data_hot03:
    driver: local
  data_warm:
    driver: local

#네트워크 설정
networks:
  default:
    name: elastic
    external: true # 기존에 만들어둔 네트워크 사용&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;.env&lt;/h4&gt;
&lt;pre id=&quot;code_1729856399798&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#ELASTIC_PASSWORD=elastic

#KIBANA_PASSWORD=elastic

STACK_VERSION=8.15.3

CLUSTER_NAME=docker-cluster

ES_PORT=9200

KIBANA_PORT=5601

ES_MEM_LIMIT=1000000000
KB_MEM_LIMIT=1000000000&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker-copose.yml과 .env를 같은 파일내에 두고 docker-compose up을 실행시키면 Elasticsearch cluster를 구성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무도 안들어오지만 혹여라도 보신분들은 테스트 시 잘 사용하셨으면 좋겠네요ㅎ&lt;br /&gt;다음에 기회가 된다면 보안설정도 추가한 docker-compose 파일도 작성해보도록 하겠습니다..!&lt;/p&gt;</description>
      <category>Elasticsearch</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/14</guid>
      <comments>https://baektothefuture.tistory.com/14#entry14comment</comments>
      <pubDate>Fri, 25 Oct 2024 20:42:55 +0900</pubDate>
    </item>
    <item>
      <title>Java - 병렬처리 (Future 인터페이스 활용)</title>
      <link>https://baektothefuture.tistory.com/13</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;90만건 가까이 되는 데이터를 Elasticsearch에서 읽어 전처리 후 다시 Elasticsearch에 색인했었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정에서 약 3~4시간정도 소요가 되는데 이를 어떻게하면 빠르게 처리할 수 있을까 고민하다가 여러개의 파일을 읽고 처리하는 과정에서 병렬처리를 활용하면 어떨까 생각이 들어 공부해보았습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Future 예시&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;출처 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;a href=&quot;https://pjh3749.tistory.com/280&quot;&gt;&lt;b&gt;https://pjh3749.tistory.com/280&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1728709028909&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class FutureMain {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future&amp;lt;Double&amp;gt; future = executorService.submit(new Callable&amp;lt;Double&amp;gt;() {
            public Double call() throws InterruptedException {
                return someLongComputation();
            }
        });
        doSomethingElse();
        try {
            Double result = future.get(1, TimeUnit.SECONDS); // &amp;lt;--- 블록 방지
            System.out.println(&quot;result : &quot; + result);
        } catch (InterruptedException e) {
            e.printStackTrace();
            // handle e
        } catch (ExecutionException e) {
            e.printStackTrace();
            // handle e
        } catch (TimeoutException e) {
            e.printStackTrace();
            executorService.shutdown();
            // handle e
        }
    }

    private static Double someLongComputation() throws InterruptedException {
        // do something
        System.out.println(&quot;someLongComputation&quot;);
        Thread.sleep(2000);
        return 1d;
    }

    private static void doSomethingElse() {
        // do something else
        System.out.println(&quot;doSomethingElse&quot;);

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;doSomethingElse&lt;br /&gt;someLongComputation&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;java.util.concurrent.TimeoutException&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;at&amp;nbsp;java.base/java.util.concurrent.FutureTask.get(FutureTask.java:204)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;at&amp;nbsp;main.FutureMain.main(FutureMain.java:16)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Process&amp;nbsp;finished&amp;nbsp;with&amp;nbsp;exit&amp;nbsp;code&amp;nbsp;0&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java 5 버전에 나온 비동기 연산을 할때 사용되는 인터페이스입니다. 시간이 오래걸릴 것 같은 작업을 Future를 활용해 작업을 하고 다른 작업을 할 수 있다는 장점이 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 보면  ExecutorService와 Future 인터페이스가 같이쓰이는것을 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 스레드 Pool을 관리해주는 인터페이스이며 Executors를 통해 여러가지의 스레드 풀을 생성할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;CachedThreadPool&lt;/b&gt;&lt;br /&gt;일정시간동안 스레드를 검색하여 60초 동안 동작이 없을 시 Thread Pool에서 제거한다. Thread의 제한 없이 무한정 생성되며, 해당 Thread가 작업이 60초간 없을 시 제거하는 방식이므로 삭제속도보다 생성되는 양이 더 많다면 효율적이지 못할 수 있기 때문에. &lt;br /&gt;최대 스레드 생성개수, 타임아웃을 설정해주는 것이 바람직해보인다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;FixedThreadPool&lt;/b&gt;&lt;br /&gt;고정된 스레드 개수만큼 생성&lt;br /&gt;&lt;br /&gt;&lt;b&gt;SingleThreadExecutor&lt;/b&gt;&lt;br /&gt;단일 스레드&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와같이 스레드를 만들어 ExecutorService 객체작업을 할당할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;할당 방법도 여러가지가 있는데 그 중 2가지를 알아보면 아래와 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;execute() : 리턴타입이 없으며 Runnable 객체로 작업을 할당받는다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;submit() : Future 객체로 리턴을 하며 Callable 객체로 작업을 할당받는다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;ExecutorService의 작업 할당과정에서 return 값을 Future 객체로 반환해주기 때문에 같이 쓰이는 것을 확인할 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Future를 활용하면 비동기적으로 작업을 처리할 수 있다는 장점이 있는데요&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 연산을 결합하기 어렵다&lt;/li&gt;
&lt;li&gt;비동기 처리 중에 발생하는 예외를 처리하기 어렵다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라는 문제가 있어 개선된 버전인 CompletableFuture 클래스가 Java 8에 업데이트 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Future vs CompletableFuture&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;출처 : &lt;a href=&quot;https://11st-tech.github.io/2024/01/04/completablefuture/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://11st-tech.github.io/2024/01/04/completablefuture/&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 91px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;Future&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;CompletableFuture&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;Blocking&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;non-blocking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;여러 연산을 함께 연결하기 어려움&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;여러 연산을 함께 연결&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;여러 연산 결과를 결합하기 어려움&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;여러 연산 결과를 결합&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;연산 성공 여부만 확인할 수 있고 예외처리 어려움&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;execeptionally(), handle()을 통한 예외 처리&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이어서 작성하면 좋겠지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 예제 코드들을 충분히 돌려보지 않았기 때문에 다음글에 이어서 작성하도록 하겠습니다..!&lt;/p&gt;</description>
      <category>Java</category>
      <category>CompletableFuture</category>
      <category>Future</category>
      <category>java</category>
      <category>multiprocessing</category>
      <category>병렬처리</category>
      <category>비동기</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/13</guid>
      <comments>https://baektothefuture.tistory.com/13#entry13comment</comments>
      <pubDate>Sat, 12 Oct 2024 15:32:19 +0900</pubDate>
    </item>
    <item>
      <title>Curator에 대해</title>
      <link>https://baektothefuture.tistory.com/12</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 생애주기 관리 프로세스를 개발중입니다..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래라면 ILM 을 활용하여 페이즈(Hot, Warm, Cold)를 결정하는것이 적절하나&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 관리 시스템이 특별한 상황일 경우(항상 writable, 언더바(_)가 활용된 Index pattern) ILM을 활용하기 어려웠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 Curator + Shell Script 를 활용하여 ILM 을 대체할 프로세스를 소개하려고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;목표&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 지난달 데이터를 Warm 페이즈로 Rollover&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Warm 노드에 있는 데이터는 primary shard 축소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;예시&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;configuration File&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/elasticsearch/client/curator/current/configfile.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.elastic.co/guide/en/elasticsearch/client/curator/current/configfile.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1728450220873&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Configuration File | Curator Reference [8.0] | Elastic&quot; data-og-description=&quot;All hosts must be in HTTP[S]://FQDN.DOMAIN.TLD:PORT form or they will be rejected and Curator will exit with an error. The only exception to this is HTTPS://FQDN.DOMAIN.TLD (without port), in which case :443 is implicit, and is, in fact, appended automatic&quot; data-og-host=&quot;www.elastic.co&quot; data-og-source-url=&quot;https://www.elastic.co/guide/en/elasticsearch/client/curator/current/configfile.html&quot; data-og-url=&quot;https://www.elastic.co/guide/en/elasticsearch/client/curator/current/configfile.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/elasticsearch/client/curator/current/configfile.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.elastic.co/guide/en/elasticsearch/client/curator/current/configfile.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Configuration File | Curator Reference [8.0] | Elastic&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;All hosts must be in HTTP[S]://FQDN.DOMAIN.TLD:PORT form or they will be rejected and Curator will exit with an error. The only exception to this is HTTPS://FQDN.DOMAIN.TLD (without port), in which case :443 is implicit, and is, in fact, appended automatic&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.elastic.co&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정 파일의 경우 해당 예시를 복사하여 hosts 부분을 Elasticsearch의 클러스터로 변경해 주었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;action_file.yml&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1728449978465&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;actions:
  1:
    action: allocation
    description: &quot;apply shard allocation&quot;
    options:
      key: tier
      value: warm
      allocation_type: require
    filters:
    - filtertype: pattern
      kind: regex
      value: '^lucy_test_v[1-9]_\d{8}$'
    - filtertype: allocated
      key: tier
      value: hot
      allocation_type: require
      exclude: False
  2:
    action: shrink
    ...
  3: 
    action: index_settings&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;간단 설명&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;actions:&lt;/b&gt; 를 통해 action_file.yml을 작성할 경우 1, 2를 통해 &lt;b&gt;action&lt;/b&gt;을 지정할 수 있다 .&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;options&lt;/b&gt;를 통해 목적 설정을 할 수 있고&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;filters&lt;/b&gt;통해 타겟 인덱스를 지정할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재는 allocation을 쓰지 않고&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;shrink action의 allocation 설정을 활용중 입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식문서를 살펴보면 shrink를 활용하기 위한 조건이 있으니 꼭 꼭 확인하고 사용하세요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/elasticsearch/client/curator/current/shrink.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.elastic.co/guide/en/elasticsearch/client/curator/current/shrink.html&lt;/a&gt;&lt;/p&gt;</description>
      <category>Elasticsearch</category>
      <category>curator</category>
      <category>Elasticsearch</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/12</guid>
      <comments>https://baektothefuture.tistory.com/12#entry12comment</comments>
      <pubDate>Wed, 9 Oct 2024 19:30:17 +0900</pubDate>
    </item>
    <item>
      <title>Kafka Monitoring 환경 구축</title>
      <link>https://baektothefuture.tistory.com/11</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 카프카 Lag을 모니터링 하기 위한 Grafana 모니터링 환경을 구축하려고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 것들을 설치했고, 어떻게 구성했는지 기록하며 복기해보도록 하겠습니다..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;설치 목록&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kafka-exporter&lt;/li&gt;
&lt;li&gt;prometheus&lt;/li&gt;
&lt;li&gt;grafana&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;설치 환경 - 리눅스&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;localhost
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kafka-exporter (docker)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;prometheus (bin)&lt;/li&gt;
&lt;li&gt;grafana (bin)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Test-Server
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Kafka&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. kafka-exporter 설치&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설치&lt;/b&gt; :&amp;nbsp;&lt;a href=&quot;https://hub.docker.com/r/danielqsj/kafka-exporter&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://hub.docker.com/r/danielqsj/kafka-exporter&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1725013211981&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;https://hub.docker.com/r/danielqsj/kafka-exporter&quot; data-og-description=&quot;&quot; data-og-host=&quot;hub.docker.com&quot; data-og-source-url=&quot;https://hub.docker.com/r/danielqsj/kafka-exporter&quot; data-og-url=&quot;https://hub.docker.com/r/danielqsj/kafka-exporter&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/syTtF/hyWVZiK6sY/X8fwME2QguhPL7JjJTvPK1/img.png?width=3372&amp;amp;height=1896&amp;amp;face=0_0_3372_1896&quot;&gt;&lt;a href=&quot;https://hub.docker.com/r/danielqsj/kafka-exporter&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hub.docker.com/r/danielqsj/kafka-exporter&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/syTtF/hyWVZiK6sY/X8fwME2QguhPL7JjJTvPK1/img.png?width=3372&amp;amp;height=1896&amp;amp;face=0_0_3372_1896');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;https://hub.docker.com/r/danielqsj/kafka-exporter&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hub.docker.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;docker run -ti --rm -p 9308:9308 danielqsj/kafka-exporter --kafka.server=&amp;lt;kafka&amp;gt;:9092&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;  설치 할 시 kafka.server가 잡히지 않는다면 체크해봐야할 사항&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kafka 실행중인지 확인&lt;/li&gt;
&lt;li&gt;kafka의 config (config/kraft/) 폴더 내 server.properties 파일 확인
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;advertised.listeners 설정에 PLAINTEXT://&amp;lt;host ip&amp;gt;:9092 설정 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;방화벽 확인 : 해당 포트 열려있는지 확인&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;sudo&amp;nbsp;firewall-cmd&amp;nbsp;--permanent&amp;nbsp;--add-port=9092/tcp&lt;/li&gt;
&lt;li&gt;sudo firewall-cmd --reload&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. prometheus 설치 및 설정&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설치&lt;/b&gt; : &lt;a style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot; href=&quot;https://github.com/prometheus/prometheus/releases/download/v2.54.1/prometheus-2.54.1.linux-amd64.tar.gz&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/prometheus/prometheus/releases/download/v2.54.1/prometheus-2.54.1.linux-amd64.tar.gz&lt;/a&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1725014508502&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# my global config
global:
 scrape_interval: 1s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
 evaluation_interval: 1s # Evaluate rules every 15 seconds. The default is every 1 minute.
 # scrape_timeout is set to the global default (10s).
# Alertmanager configuration
alerting:
 alertmanagers:
 - static_configs:
 - targets:
 # - alertmanager:9093
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
 # - &quot;first_rules.yml&quot;
 # - &quot;second_rules.yml&quot;
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
 # The job name is added as a label `job=&amp;lt;job_name&amp;gt;` to any timeseries scraped from this config
 - job_name: &quot;&amp;lt;이름 설정&amp;gt;&quot;
	 # metrics_path defaults to '/metrics'
	 # scheme defaults to 'http'.
 static_configs:
 - targets: [&quot;&amp;lt;localhost&amp;gt;:9308&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. Grafana&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설치&lt;/b&gt; :&amp;nbsp;&lt;a href=&quot;https://grafana.com/grafana/download?pg=get&amp;amp;plcmt=selfmanaged-box1-cta1&amp;amp;platform=linux&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://grafana.com/grafana/download?pg=get&amp;amp;plcmt=selfmanaged-box1-cta1&amp;amp;platform=linux&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1725014670534&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Download Grafana | Grafana Labs&quot; data-og-description=&quot;Overview of how to download and install different versions of Grafana on different operating systems.&quot; data-og-host=&quot;grafana.com&quot; data-og-source-url=&quot;https://grafana.com/grafana/download?pg=get&amp;amp;plcmt=selfmanaged-box1-cta1&amp;amp;platform=linux&quot; data-og-url=&quot;https://grafana.com/grafana/download?pg=get&amp;amp;platform=linux&amp;amp;plcmt=selfmanaged-box1-cta1&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bu6oBN/hyWV5iXLVq/EZCq2kxxuKRO6MfyeuMdCk/img.png?width=900&amp;amp;height=780&amp;amp;face=0_0_900_780&quot;&gt;&lt;a href=&quot;https://grafana.com/grafana/download?pg=get&amp;amp;plcmt=selfmanaged-box1-cta1&amp;amp;platform=linux&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://grafana.com/grafana/download?pg=get&amp;amp;plcmt=selfmanaged-box1-cta1&amp;amp;platform=linux&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bu6oBN/hyWV5iXLVq/EZCq2kxxuKRO6MfyeuMdCk/img.png?width=900&amp;amp;height=780&amp;amp;face=0_0_900_780');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Download Grafana | Grafana Labs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Overview of how to download and install different versions of Grafana on different operating systems.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;grafana.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;dashboard -&amp;gt; kafka에 맞는 화면을 구성해줍니다!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설치&lt;/b&gt; : &lt;a href=&quot;https://grafana.com/grafana/dashboards/7589-kafka-exporter-overview/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://grafana.com/grafana/dashboards/7589-kafka-exporter-overview/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1725014686936&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Kafka Exporter Overview | Grafana Labs&quot; data-og-description=&quot;Thank you! Your message has been received!&quot; data-og-host=&quot;grafana.com&quot; data-og-source-url=&quot;https://grafana.com/grafana/dashboards/7589-kafka-exporter-overview/&quot; data-og-url=&quot;https://grafana.com/grafana/dashboards/7589-kafka-exporter-overview/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cvYqz1/hyWVUV2poj/DQC9OhABId8rWGwOOQEQzK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bNTbnV/hyWV1ARwA4/TRTKm0bsUpRUk6E6RzAqY0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://grafana.com/grafana/dashboards/7589-kafka-exporter-overview/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://grafana.com/grafana/dashboards/7589-kafka-exporter-overview/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cvYqz1/hyWVUV2poj/DQC9OhABId8rWGwOOQEQzK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bNTbnV/hyWV1ARwA4/TRTKm0bsUpRUk6E6RzAqY0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Kafka Exporter Overview | Grafana Labs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Thank you! Your message has been received!&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;grafana.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;실행화면&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2184&quot; data-origin-height=&quot;1062&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/27YXd/btsJmtkbdSB/zsjMYdagV4KOKcuIBKFWJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/27YXd/btsJmtkbdSB/zsjMYdagV4KOKcuIBKFWJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/27YXd/btsJmtkbdSB/zsjMYdagV4KOKcuIBKFWJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F27YXd%2FbtsJmtkbdSB%2FzsjMYdagV4KOKcuIBKFWJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2184&quot; height=&quot;1062&quot; data-origin-width=&quot;2184&quot; data-origin-height=&quot;1062&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 해서 모니터링 화면을 구성해보았습니다..!&lt;/p&gt;</description>
      <category>Kafka</category>
      <category>grafana</category>
      <category>kafka</category>
      <category>kafka-exporter</category>
      <category>monitoring</category>
      <category>Prometheus</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/11</guid>
      <comments>https://baektothefuture.tistory.com/11#entry11comment</comments>
      <pubDate>Fri, 30 Aug 2024 19:52:09 +0900</pubDate>
    </item>
    <item>
      <title>Kafka + HPA 테스트</title>
      <link>https://baektothefuture.tistory.com/10</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;쿠버네티스를 공부해보며 도입해볼만한 것들을 추리고 있는데, HPA를 활용한 어플리케이션 병렬처리가 Kafka의 Consumer Group을 다루기에 궁합이 좋다고 느껴 테스트를 해보았습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;++ Kafka 선택 이유&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레디스와 카프카를 고민해보긴했는데&amp;nbsp;온프레미스 환경에서 서비스가 돌아가기 때문에 In-memory로는 Scale-out, Scale-up에 한계가 있어 카프카를 선택하게 되었습니다.&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1494&quot; data-origin-height=&quot;704&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qhLD8/btsIIjwaqBW/DYJyGGUO8MehCb7HPKaW21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qhLD8/btsIIjwaqBW/DYJyGGUO8MehCb7HPKaW21/img.png&quot; data-alt=&quot;테스트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qhLD8/btsIIjwaqBW/DYJyGGUO8MehCb7HPKaW21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqhLD8%2FbtsIIjwaqBW%2FDYJyGGUO8MehCb7HPKaW21%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;620&quot; height=&quot;292&quot; data-origin-width=&quot;1494&quot; data-origin-height=&quot;704&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;테스트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;실행환경&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;local&lt;/b&gt; : minikube&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;내부망&lt;/b&gt; : Server 1 (Kafka)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;동작&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Elasticsearch 에서 문서를 가져와 Kafka (topic 1)에 적재&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. topic 1에 적재된 문서들을 가져와 전처리 (간단한 Key, value 추가) 후 다시 Kafka (topic 2)에 적재&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Kafka client&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1722779979097&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class KafkaUtil {

    private static final String bootstrapServer = &quot;192.168.125.64:9092&quot;;
    Properties properties = new Properties();

    private Properties setProperties(SwitchParameters switchParameters) {
        switch (switchParameters) {
            case producer:
                properties.setProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServer);
                // 전송/수신 하는 데이터에 맞추어 Serializer 설정 -&amp;gt; 문자열일 시 StringSerializer
                properties.setProperty(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
                properties.setProperty(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
                properties.setProperty(ProducerConfig.ACKS_CONFIG, &quot;all&quot;);
                properties.setProperty(ProducerConfig.MAX_BLOCK_MS_CONFIG, &quot;30000&quot;);
                return properties;
            case consumer:
                properties.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServer);
                // 전송/수신 하는 데이터에 맞추어 Serializer 설정 -&amp;gt; 문자열일 시 StringSerializer
                properties.setProperty(ConsumerConfig.GROUP_ID_CONFIG, &quot;testtopic&quot;);
                properties.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
                properties.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
                properties.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, &quot;earliest&quot;);

                return properties;
        }
        return null;
    }

    public KafkaProducer getProducer() {
        properties = setProperties(SwitchParameters.producer);
        System.out.println(&quot;get Properties : &quot; + properties);
        KafkaProducer&amp;lt;String, String&amp;gt; producer = new KafkaProducer&amp;lt;&amp;gt;(properties);
        return producer;
    }

    public KafkaConsumer getConsumer() {
        properties = setProperties(SwitchParameters.consumer);
        KafkaConsumer&amp;lt;String, String&amp;gt; consumer = new KafkaConsumer&amp;lt;&amp;gt;(properties);
        return consumer;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; Maven 환경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Client를 이용해 pub, sub 기능 구현&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Kafka-hpa.yaml&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1722780185022&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
	name: kafka-hpa
spec:
	selector:
		matchLabels:
			run: kafka-hpa
	replicas: 1
	template:
		metadata:
			labels:
				run: kafka-hpa
		spec:
			containers:
				- name: kafka-hpa
					image: baektothefuture98/kafkatest:0.0.5
					ports: 
						- container: 9092
					resources:
						limits:
							memory: 128Mi
							cpu: 500m
						requests:
							memory: 64Mi
							cpu: 300m
___
apiVersion: v1
kind: Service
metadata:
	name: kafka-hpa
	labels:
		run: kafka-hpa
spec:
	ports:
		- port: 0
	selector:
		run: kafka-hpa&lt;/code&gt;&lt;/pre&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 Yaml 파일 작성 후 아래 명령어로 등록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. kubectl apply -f &amp;lt;kafka-hpa.yaml 파일 위치&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. kubectl autoscale deployment/kafka-hpa --min=1 --max=4 --cpu-percent=10&lt;br /&gt;-&amp;gt; 최소 1개의 pod - 최대 4개의 pod까지 / cpu 한계 10 퍼센트일 시 적용 (테스트 차 낮게 적용)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Kafka 모니터링 도구 - 임시&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/provectus/kafka-ui&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/provectus/kafka-ui&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1722781217085&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - provectus/kafka-ui: Open-Source Web UI for Apache Kafka Management&quot; data-og-description=&quot;Open-Source Web UI for Apache Kafka Management. Contribute to provectus/kafka-ui development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/provectus/kafka-ui&quot; data-og-url=&quot;https://github.com/provectus/kafka-ui&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cMUoOG/hyWKzjwCME/bQwwWqghl9brbVa5aPPEVk/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640&quot;&gt;&lt;a href=&quot;https://github.com/provectus/kafka-ui&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/provectus/kafka-ui&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cMUoOG/hyWKzjwCME/bQwwWqghl9brbVa5aPPEVk/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - provectus/kafka-ui: Open-Source Web UI for Apache Kafka Management&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Open-Source Web UI for Apache Kafka Management. Contribute to provectus/kafka-ui development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;결과&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kubectl get hpa를 통해 CPU 한계 시 replicas(pod)가 늘어나는지 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; Consumer 어플리케이션에 HTTP API가 없기에 K6 테스트가 아닌 한계를 낮춰 파드 증가 확인&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2502&quot; data-origin-height=&quot;1274&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLRKBk/btsITtSKBZl/M53R73CiWrnr7xsagVkv71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLRKBk/btsITtSKBZl/M53R73CiWrnr7xsagVkv71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLRKBk/btsITtSKBZl/M53R73CiWrnr7xsagVkv71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLRKBk%2FbtsITtSKBZl%2FM53R73CiWrnr7xsagVkv71%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2502&quot; height=&quot;1274&quot; data-origin-width=&quot;2502&quot; data-origin-height=&quot;1274&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Replicas가 1 -&amp;gt; 4로 CPU 증가량에 따라 설정된 MaxPods만큼 증가하는 것을 확인&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;&lt;b&gt;minikube dashboard&amp;nbsp; 확인&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_blob&quot; data-origin-width=&quot;2874&quot; data-origin-height=&quot;1128&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3tXdV/btsISXteLk6/l3yaIC1YZTf8kCpFVLsqk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3tXdV/btsISXteLk6/l3yaIC1YZTf8kCpFVLsqk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3tXdV/btsISXteLk6/l3yaIC1YZTf8kCpFVLsqk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3tXdV%2FbtsISXteLk6%2Fl3yaIC1YZTf8kCpFVLsqk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;863&quot; height=&quot;341&quot; data-filename=&quot;edited_blob&quot; data-origin-width=&quot;2874&quot; data-origin-height=&quot;1128&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 총 100만건 인입&lt;/b&gt;&lt;br /&gt;평균 전송 속도 (100건 기준) : 0.071 sec&lt;br /&gt;CPU&amp;nbsp;사용률&amp;nbsp;(LOAD)&amp;nbsp;&amp;nbsp;:&amp;nbsp;최대&amp;nbsp;90%&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>쿠버네티스</category>
      <category>HPA</category>
      <category>kafka</category>
      <category>kubernetes</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/10</guid>
      <comments>https://baektothefuture.tistory.com/10#entry10comment</comments>
      <pubDate>Sun, 4 Aug 2024 23:57:22 +0900</pubDate>
    </item>
    <item>
      <title>[K8s] 크론잡 기본활용_Cronjob</title>
      <link>https://baektothefuture.tistory.com/9</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt; &amp;nbsp; 개요&lt;br /&gt;현 서비스 중 리눅스의 Crontab을 사용하고 있는 어플리케이션을 쿠버네티스 환경으로 전환하기&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;u&gt;쿠버네티스에 대한 전반적인 지식은 공식 Document와 &quot;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;컨테이너 인프라 환경 구축을 위한 쿠버네티스/도커&quot;&amp;nbsp; 도서에서 공부하였습니다.&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;구성환경&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;서버 : Local (Minikube)&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;참고 : &lt;a href=&quot;https://minikube.sigs.k8s.io/docs/start/?arch=%2Fmacos%2Fx86-64%2Fstable%2Fbinary+download&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://minikube.sigs.k8s.io/docs/start/?arch=%2Fmacos%2Fx86-64%2Fstable%2Fbinary+download&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1720953996679&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;minikube start&quot; data-og-description=&quot;minikube is local Kubernetes, focusing on making it easy to learn and develop for Kubernetes. All you need is Docker (or similarly compatible) container or a Virtual Machine environment, and Kubernetes is a single command away: minikube start What you&amp;rsquo;ll&quot; data-og-host=&quot;minikube.sigs.k8s.io&quot; data-og-source-url=&quot;https://minikube.sigs.k8s.io/docs/start/?arch=%2Fmacos%2Fx86-64%2Fstable%2Fbinary+download&quot; data-og-url=&quot;https://minikube.sigs.k8s.io/docs/start/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://minikube.sigs.k8s.io/docs/start/?arch=%2Fmacos%2Fx86-64%2Fstable%2Fbinary+download&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://minikube.sigs.k8s.io/docs/start/?arch=%2Fmacos%2Fx86-64%2Fstable%2Fbinary+download&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;minikube start&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;minikube is local Kubernetes, focusing on making it easy to learn and develop for Kubernetes. All you need is Docker (or similarly compatible) container or a Virtual Machine environment, and Kubernetes is a single command away: minikube start What you&amp;rsquo;ll&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;minikube.sigs.k8s.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;➡️ kubectl 업그레이드 필요&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;기본개념&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;434&quot; data-origin-height=&quot;448&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMcqCm/btsIx6Ej46l/mgkSkJ0Se11KbWKwnyXDl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMcqCm/btsIx6Ej46l/mgkSkJ0Se11KbWKwnyXDl0/img.png&quot; data-alt=&quot;Cronjob 실행 과정 (출처 : 무신사 테크)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMcqCm/btsIx6Ej46l/mgkSkJ0Se11KbWKwnyXDl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMcqCm%2FbtsIx6Ej46l%2FmgkSkJ0Se11KbWKwnyXDl0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;434&quot; height=&quot;448&quot; data-origin-width=&quot;434&quot; data-origin-height=&quot;448&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Cronjob 실행 과정 (출처 : 무신사 테크)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;957&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/peyVN/btsIyjJYpOO/9J17oW1iEAsRdWFkM2qac1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/peyVN/btsIyjJYpOO/9J17oW1iEAsRdWFkM2qac1/img.png&quot; data-alt=&quot;Cronjob workflow, Deployment와 비교 (출처 : 무신사 테크)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/peyVN/btsIyjJYpOO/9J17oW1iEAsRdWFkM2qac1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpeyVN%2FbtsIyjJYpOO%2F9J17oW1iEAsRdWFkM2qac1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;733&quot; height=&quot;230&quot; data-origin-width=&quot;957&quot; data-origin-height=&quot;300&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Cronjob workflow, Deployment와 비교 (출처 : 무신사 테크)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;Cronjob Manifest 파일 구조&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1720954576250&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# -------------------------------- Cronjob 부분
apiVersion : batch/v1
kind: Cronjob # 유형 지정

metadata:
	# ...
spec:
	schedule: &quot;*/1 * * * *&quot; #1분마다 실행
    # ...
    # --------------------------- Job 부분
    jobTemplate:
    	# ...
        # ----------------------- Pod 부분
		template: 
        	metadata: 
            # ...
            containers: 
            	- name:
                  image: &amp;lt;docker image&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;Test&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사용파일&lt;/b&gt; : System.out.println(&quot;Hello Docker!&quot;); 여러개로 구성된 간단한 Java 어플리케이션&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. DockerFile 작성&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1720954846313&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;FROM maven:3.6.3-jdk-8-slim AS build

COPY ../.. /root/sources

WORKDIR /root/sources

RUN mvn package

FROM openjdk:8-jdk-alpine

RUN mkdir /app

COPY --from=build /root/sources/target/dockerTest-1.0-SNAPSHOT.jar /app/dockerTest.jar

# ----2-3. JAR 파일 실행
CMD [&quot;java&quot;, &quot;-jar&quot;, &quot;/app/dockerTest.jar&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. docker-compose 작성&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1720954884746&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;version: '3'
services:
  bpe-test:
    image: baektothefuture98/test:0.0.1
    build:
      context: .
      dockerfile: ./Dockerfile
    ports:
      - &quot;80:8080&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. pom.xml 설정&lt;/b&gt;&lt;br /&gt;➡️ maven project를 docker 이미지로 묶는 과정에서 오류 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; -해결 : shade dependency plugin 적용&lt;/p&gt;
&lt;pre id=&quot;code_1720954958075&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    &amp;lt;!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-shade-plugin --&amp;gt;
   &amp;lt;dependency&amp;gt;
      &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
      &amp;lt;artifactId&amp;gt;maven-shade-plugin&amp;lt;/artifactId&amp;gt;
      &amp;lt;version&amp;gt;3.6.0&amp;lt;/version&amp;gt;
   &amp;lt;/dependency&amp;gt;
    
  &amp;lt;build&amp;gt;
  &amp;lt;plugins&amp;gt;
    &amp;lt;plugin&amp;gt;
      &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
      &amp;lt;artifactId&amp;gt;maven-shade-plugin&amp;lt;/artifactId&amp;gt;
      &amp;lt;version&amp;gt;3.6.0&amp;lt;/version&amp;gt;
      &amp;lt;configuration&amp;gt;
        &amp;lt;transformers&amp;gt;
          &amp;lt;transformer
                  implementation=&quot;org.apache.maven.plugins.shade.resource.ManifestResourceTransformer&quot;&amp;gt;
            &amp;lt;mainClass&amp;gt; 실행할 main 클래스 위치 지정(Source 파일 기준) &amp;lt;/mainClass&amp;gt;
          &amp;lt;/transformer&amp;gt;
        &amp;lt;/transformers&amp;gt;
      &amp;lt;/configuration&amp;gt;
      &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
          &amp;lt;phase&amp;gt;package&amp;lt;/phase&amp;gt;
          &amp;lt;goals&amp;gt;
            &amp;lt;goal&amp;gt;shade&amp;lt;/goal&amp;gt;
          &amp;lt;/goals&amp;gt;
        &amp;lt;/execution&amp;gt;
      &amp;lt;/executions&amp;gt;
    &amp;lt;/plugin&amp;gt;
  &amp;lt;/plugins&amp;gt;
  &amp;lt;/build&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. docker hub에 올리기 (혹은 Harbor)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker-compose build ➡️ docker-compose up (local에 올리기) &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;➡️ docker-compose push (docker hub에 배포)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;5. Cronjob YAML 파일 작성하여 배포&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Cronjob.yaml&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1720955157310&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: batch/v1
kind: CronJob
metadata:
  name: bpe-test
  namespace: default
spec:
  schedule: &quot;*/1 * * * *&quot;
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 3
  jobTemplate:
    spec:
      ttlSecondsAfterFinished: 30
      backoffLimit: 0
      template:
        spec:
          containers:
            - name: bpe-test
              image: &amp;lt;도커 허브 아이디 : baektothefuture98&amp;gt;/test:0.0.1
          restartPolicy: Never&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Cronjob YAML 파헤치기&lt;/b&gt;&lt;br /&gt;metadata.namespace : 쿠버네티스 클러스터내의 논리적 분리 단위&amp;nbsp;&lt;br /&gt;&amp;rarr;&amp;nbsp;이름으로&amp;nbsp;구분하며&amp;nbsp;namespace.yaml&amp;nbsp;파일에서&amp;nbsp;명시가&amp;nbsp;되어있어야&amp;nbsp;사용&amp;nbsp;가능&lt;br /&gt;spec.schedule : 시간 설정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;spec.concurrencyPolicy&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Allow&amp;nbsp;&amp;nbsp;:&amp;nbsp;old&amp;nbsp;Job,&amp;nbsp;new&amp;nbsp;Job&amp;nbsp;병렬처리&amp;nbsp;가능&lt;/li&gt;
&lt;li&gt;Replace&amp;nbsp;:&amp;nbsp;새로운&amp;nbsp;Job이&amp;nbsp;발생&amp;nbsp;시&amp;nbsp;이전&amp;nbsp;Job&amp;nbsp;종료&lt;/li&gt;
&lt;li&gt;Forbid&amp;nbsp;:&amp;nbsp;이전&amp;nbsp;Job이&amp;nbsp;완료되지&amp;nbsp;않았다면&amp;nbsp;새로운&amp;nbsp;Job&amp;nbsp;건너뛰기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;spec.successfulJobsHistoryLimit&amp;nbsp;:&amp;nbsp;성공한&amp;nbsp;Job&amp;nbsp;기록을&amp;nbsp;N개&amp;nbsp;남기기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;spec.failedJobsHistoryLimit&amp;nbsp;:&amp;nbsp;실패한&amp;nbsp;Job&amp;nbsp;기록을&amp;nbsp;N개&amp;nbsp;남기기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;JOB&lt;/b&gt;&lt;br /&gt;ttlSecondAfterFinished : 완료된 Job 자동 정리&lt;br /&gt;&lt;u&gt;&amp;rarr;&amp;nbsp;완료된&amp;nbsp;Job은&amp;nbsp;자동으로&amp;nbsp;사라지지&amp;nbsp;않기&amp;nbsp;때문에&amp;nbsp;리소스를&amp;nbsp;차지하므로&amp;nbsp;정리&amp;nbsp;필요&lt;/u&gt;&lt;br /&gt;backoffLimit : 재시도 횟수&amp;nbsp;&lt;br /&gt;&amp;rarr;&amp;nbsp;몇&amp;nbsp;회의&amp;nbsp;재시도&amp;nbsp;이후에&amp;nbsp;잡이&amp;nbsp;실패되도록&amp;nbsp;만들어야&amp;nbsp;하는&amp;nbsp;경우&lt;br /&gt;&lt;a href=&quot;https://kubernetes.io/ko/docs/concepts/workloads/controllers/job/#파드-백오프-backoff-실패-정책&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://kubernetes.io/ko/docs/concepts/workloads/controllers/job/#파드-백오프-backoff-실패-정책&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Pod&lt;/b&gt;&lt;br /&gt;container.image : 도커 이미지 지정&lt;br /&gt;restartPolicy :&amp;nbsp;&lt;br /&gt;Always : 항상 재시작&amp;nbsp;&lt;br /&gt;OnFailure : 비정상 종료 시 재시작&lt;br /&gt;Never : 컨테이너를 재시작 하지 않음&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매우매우 간단한 파일로 docker image, docker-compose를 구성하여 크론잡을 구성해 보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저처럼 쿠버네티스에 대한 지식이 부족한 분들에게 조금이나마 도움이 되길 바랍니다,,,!&lt;/p&gt;</description>
      <category>쿠버네티스</category>
      <category>cronjob</category>
      <category>k8s</category>
      <category>kubernetes</category>
      <category>쿠버네티스</category>
      <category>크론잡</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/9</guid>
      <comments>https://baektothefuture.tistory.com/9#entry9comment</comments>
      <pubDate>Mon, 15 Jul 2024 20:03:28 +0900</pubDate>
    </item>
    <item>
      <title>Elasticsearch ILM 탐색기</title>
      <link>https://baektothefuture.tistory.com/8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;그동안 자사 서비스의 최신/과거 데이터 관리를 크론탭을 활용하여 자바 프로세스를 통해 관리를 했다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번엔 Elasticsearch의 기능 중 하나인 ILM을 통해 자체적으로 자동화를 할 수 있는지 알아보겠습니다..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ILM을 통해 관리한다는 것은,,! 자동으로 Phase를 옮긴다는 것과 같은 말이라고 생각합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 애석하게도 서비스의 노드마다 elasticsearch.yml 설정인 node.roles를 상세하게 설정해놓지 않았습니다.(master냐? data냐?) node.attr.tier을 통해 구분할 뿐 node의 역할을 명시해 놓지 않았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대신. yml 파일에 node.attr을 통해 설정하므로써 노드에 속성을 부여해주며 구분을 지었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;( Node attribute에 대해 공식문서 링크해드리려 했는데 없습니다,, ㅎ ㅠㅠ 찾으면 알려주세요)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;즉 ! &quot;node.attr으로 구분한 클러스터에 ILM 적용하기&quot;가 이 글의 주제가 되겠습니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;목표&lt;/b&gt;&lt;br /&gt;1. ILM을 활용하여 daily(hot) -&amp;gt; montly(warm)으로 phases 이동&lt;br /&gt;2. 과거 데이터는 삭제하지 않음&lt;br /&gt;3. warm phase로 이동시 primary shard 수 감소 -&amp;gt; 과거 데이터 수정을 위해 삭제하지 않음&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;환경설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 서버 : 3대&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 데이터 노드에 적용되어 있는 설정 - elasticsearch.yml&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;node.roles : [data]&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;node.attr.tier : &amp;lt;hot, warm, &amp;hellip;&amp;gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;node.attr.partition&amp;nbsp;:&amp;nbsp;&amp;lt;number&amp;gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;Kibana&lt;/b&gt; - 페이즈 변경 속도 확인 및 변경&amp;nbsp;&lt;br /&gt;&lt;b&gt;GET /_cluster/settings&lt;/b&gt;&lt;br /&gt;&lt;b&gt;PUT /_cluster/settings&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;** 페이즈 변경 및 인덱스 refresh의 간격이 좁을수록 cpu 부하 **&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. ILM 작성 &lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1718204280123&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;PUT _ilm/policy/test_policy
{
  &quot;policy&quot;: {
    &quot;phases&quot;: {
      &quot;hot&quot;: {   # ---------- 1
        &quot;min_age&quot;: &quot;0d&quot;, # ----- 1-1
        &quot;actions&quot;: {
          &quot;set_priority&quot;: { # ---- 1-2
            &quot;priority&quot;: 100
          },
          &quot;rollover&quot;: { # ------ 1-3
            &quot;max_age&quot;: &quot;30d&quot;,
            &quot;max_docs&quot;: 1000,
            &quot;max_size&quot;: &quot;5gb&quot;
          }
        }
      },
      &quot;warm&quot;: { # ----------- 2
        &quot;min_age&quot;: &quot;0d&quot;,
        &quot;actions&quot;: {
          &quot;set_priority&quot;: { # ------- 2-1
            &quot;priority&quot;: 50
          },
          &quot;allocate&quot;: { # ------ 2-2
            &quot;require&quot;: {
              &quot;tier&quot; : &quot;warm&quot;
            }
          }, 
          &quot;shrink&quot;: {
            &quot;number_of_shards&quot;: 1
          },
          &quot;forcemerge&quot;: {
            &quot;max_num_segments&quot;: 1
          }
        }
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. &quot;hot&quot; phase&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1-1 : min_age를 0으로 설정함으로써 대기시간 없이 바로바로 hot phase로 유입된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1-2 : set_priority를 설정함으로써 phase의 우선순위를 정해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1-3 : rollover 설정 &amp;gt; 아래의 조건 중 하나라도 만족 시 새로운 인덱스로 rollover&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. &quot;warm&quot; phase&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2-1 : 1-2와 같음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2-2 : allocate 설정( 접근 위치를 설정할 수 있음) -&amp;gt; replica shard는 1개로 설정하고, &quot;require&quot; 설정을 통해 사용자가 지정한 노드에 접근&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;kibana를 통해 접근된 노드를 확인&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;692&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIXyhW/btsIgLtrGVO/DwlFxzgsVy2tkN6GaGGC7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIXyhW/btsIgLtrGVO/DwlFxzgsVy2tkN6GaGGC7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIXyhW/btsIgLtrGVO/DwlFxzgsVy2tkN6GaGGC7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIXyhW%2FbtsIgLtrGVO%2FDwlFxzgsVy2tkN6GaGGC7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;537&quot; height=&quot;692&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;692&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. Index_template 작성 및 ILM 적용&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1719644427260&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;PUT _index_template/&amp;lt;Index Template 이름&amp;gt;
{
  &quot;index_patterns&quot;: [&quot;hit-test-*&quot;],
  &quot;template&quot;: {
    &quot;settings&quot;: {
      &quot;number_of_replicas&quot;: 1,
      &quot;number_of_shards&quot;: 3,
      &quot;index.lifecycle.name&quot; :&amp;lt;ILM_POLICY_이름&amp;gt;,
      &quot;index.lifecycle.rollover_alias&quot; : &amp;lt;rollover_별칭&amp;gt;
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;nbsp;&quot;index.lifecycle.name&quot; : &amp;lt;앞서 만들었던 ILM Policy&amp;gt;&lt;/li&gt;
&lt;li&gt;&quot;index.lifecycle.rollover_alias&quot; : &amp;lt;별칭 설정&amp;gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. Rollover 별칭을 사용하여 초기 인덱스에 적용&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1719644713139&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;PUT hit-test-1
{
  &quot;aliases&quot;: {
    &amp;lt;rollover_별칭&amp;gt;: {
      &quot;is_write_index&quot;: true
    }
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TEST&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &quot;max_docs&quot;의 한계인 10개 이상 doc 넣어보기&lt;/p&gt;
&lt;pre id=&quot;code_1719645421464&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;put &amp;lt;rollover_alias&amp;gt;/_doc/15
{
  &quot;test&quot; : &quot;hi&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;초기 인덱스인 &quot;hit-test-1&quot;이 &quot;warm&quot; phase로 넘어가는 것 확인&lt;/li&gt;
&lt;li&gt;변경이 안된다면? -&amp;gt; 페이즈 변경 속도 확인 / refresh_interval 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 강제 rollover을 시켜주어 phase 넘어가는 것 확인&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PUT /rollover_alias/_rollover 를 날리면 강제 rollover 가능&lt;/li&gt;
&lt;li&gt;Rollover 조건을 강제로 변환&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1719645513415&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;POST ilm_test/_rollover
{
  &quot;conditions&quot;: {
    &quot;max_docs&quot;: 1
} }
POST ilm_test/_rollover
{
  &quot;conditions&quot;: {
    &quot;max_age&quot;: &quot;1s&quot;
} }&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2736&quot; data-origin-height=&quot;822&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZ2idY/btsIgnsOd51/3NHZHPyrWNBDQNns9RDT71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZ2idY/btsIgnsOd51/3NHZHPyrWNBDQNns9RDT71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZ2idY/btsIgnsOd51/3NHZHPyrWNBDQNns9RDT71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZ2idY%2FbtsIgnsOd51%2F3NHZHPyrWNBDQNns9RDT71%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;630&quot; height=&quot;822&quot; data-origin-width=&quot;2736&quot; data-origin-height=&quot;822&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 오류 시 &quot;is_write_index&quot; : true 설정과 &quot;indices.lifecycle.poll_interval&quot; 설정 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결과&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. ILM을 활용하여 daily(Hot) -&amp;gt; montly(Warm)으로 phase 이동 Rollover&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;※&amp;nbsp;&lt;/b&gt;&lt;br /&gt;ILM은 기본적으로 인덱스 생성 시간과 min_age 설정 기준으로 동작하기 때문에 날짜가 변경되어도 Rollover되지 않을 수 있음&lt;br /&gt;-&amp;gt; 현재 날짜에 맞추어 다루려면 Logstash와 연동 모색&lt;br /&gt;&lt;b&gt;관련 링크 :&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;a href=&quot;https://discuss.elastic.co/t/index-not-rollover-when-the-date-%20changes/272385&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://discuss.elastic.co/t/index-not-rollover-when-the-date- changes/272385&lt;/a&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. warm phase로 이동 시 primary shard 수 축소 (삭제는 하지 않음)&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;※&amp;nbsp;&lt;/b&gt;&lt;br /&gt;warm phase에서 shrink를 통해 Primary shard 수를 축소 가능하나 ILM에서의 Warm phase는 더 이상 update가 필요하지 않은 데이터이다.&lt;br /&gt;&amp;gt; primary shard 를 줄인다면 update가 불가하다. 이를 가능하게 하려면 수동으로 처리가 필요하다&lt;br /&gt;(ex - reindex, ...)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. Phase 변경 중 유입된 데이터는 어떻게 관리되는지?&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;※ Phase 변경 속도를 늦추어 Test&lt;br /&gt;변경 되기 전 인덱스로 데이터가 유입 (조건에 맞지 않는 인덱스가 발생)&lt;br /&gt;&amp;gt; ex) max_docs는 10까지가 한계임에도 조건 개수를 초과하는 인덱스가 발생한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 인덱스 이름 제한&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인덱스 이름은 ^.*-\d+$ 패턴에 일치해야 한다. (ex ilm-test-000001)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/elasticsearch/reference/7.16/indices-rollover- index.html#_using_date_math_with_the_rollover_api&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.elastic.co/guide/en/elasticsearch/reference/7.16/indices-rollover- index.html#_using_date_math_with_the_rollover_api&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ILM을 통해 이루고자 하는 목표인 자동 인덱스 관리를 하려면 부가적이 프로세스가 필요하다고 생각합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Date 관리 (29,39,31) -&amp;gt; alias : 최대 index 수명 단위가 day이며 month 단위 부터는 없다.&lt;/li&gt;
&lt;li&gt;조건 초과 index 관리 -&amp;gt; 강제 rollover 프로세스 개발 (인덱스를 검사하는 최소 interval 단위 1초)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style2&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대체 가능 프로세스 고안&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;※ 글쓴이의 개인적인 생각이므로 완벽하지 않습니다 ※&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;JAVA + ILM 혼용&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ILM : 29일, 30일, 31일에 맞춘 ILM 정책 - alias로 구분하기 때문에 정책이 다르지 않다면 한개도 가능&lt;/li&gt;
&lt;li&gt;_index_template : 1~12월의 template 총 12개 &amp;rarr; index_pattern = [service_main_2024&amp;lt;01~12&amp;gt;-*&amp;lt;day&amp;gt;]&lt;/li&gt;
&lt;li&gt;해당 월에 맞추어 ILM 적용 &amp;rarr; Rollover_alias는 12개 (alias 하나에 인덱스 하나만 적용 가능)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;순서&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Logstash
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Date에 맞추어 Elasticsearch로 데이터 전달&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Elasticsearch(_index_template)
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;day
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;crontab을 활용하여 강제 rollover&lt;/li&gt;
&lt;li&gt;생성 예시 &amp;rarr; service_main_202401-&amp;lt;000001, ... ~&amp;gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;month
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;logstash 활용하여 date에 맞게 인덱스명 변경&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Java Process
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;년도가 바뀔때마다 template 변경 필요&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기대효과&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;월별 인덱스 검색을 위한 alias 설정 안해도 된다. &amp;rarr; rollover_alias 명으로 검색 가능&lt;/li&gt;
&lt;li&gt;logstash 활용으로 Date 관리&lt;/li&gt;
&lt;li&gt;ILM 장점 활용 가능 (후처리 process 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;필요사항&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;template 수정 필요 &amp;rarr; 매년 만들어주어야 함&lt;/li&gt;
&lt;li&gt;인덱스 rollover 조건이 하루가 지나기 전 rollover이 되지 않도록 충분해야 한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;후처리 목표 (shard, index location) 위주 조건&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Logstash에서 ILM에 강제 Rollover을 걸 수 있는지 봐야한다.&lt;/li&gt;
&lt;li&gt;기존 서비스가 활용하는 인덱스 명을 ILM 규칙에 맞게 변경&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Elasticsearch</category>
      <category>Elasticsearch</category>
      <category>ILM</category>
      <category>index_pattern</category>
      <category>엘라스틱서치</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/8</guid>
      <comments>https://baektothefuture.tistory.com/8#entry8comment</comments>
      <pubDate>Sat, 29 Jun 2024 17:01:58 +0900</pubDate>
    </item>
    <item>
      <title>RAID</title>
      <link>https://baektothefuture.tistory.com/7</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 RAID에 대해 알아보도록 하겠습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;412&quot; data-origin-height=&quot;660&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqptK0/btsHB9nQ41c/q6kfKp0dOkef091NnOWkjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqptK0/btsHB9nQ41c/q6kfKp0dOkef091NnOWkjk/img.png&quot; data-alt=&quot;Disk 1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqptK0/btsHB9nQ41c/q6kfKp0dOkef091NnOWkjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdqptK0%2FbtsHB9nQ41c%2Fq6kfKp0dOkef091NnOWkjk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;122&quot; height=&quot;195&quot; data-origin-width=&quot;412&quot; data-origin-height=&quot;660&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Disk 1&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순 데이터 A, B, C, D를 디스크에 저장한다고 한다면 위 그림의 Disk1 처럼 디스크에 차곡차곡 쌓이게 될 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 데이터의 양이 늘어난다면? Disk의 용량을 높이기 위해 더 많은 비용이 들것이며 데이터를 쌓는데도 시간이 더 걸릴것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 디스크 하나로 데이터를 관리하다보면 가용성 측면에서도 매우 안좋을 것입니다,,!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;i&gt;&lt;b&gt;이에대한 해결책은? -&amp;gt; RAID&lt;/b&gt;&lt;/i&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;RAID는 아래와 같은 의미를 가지고 있습니다.&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Redundant Array of Independent Disk(독립된 디스크의 복수 배열)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- Redundant Array of Inexpensive Disk(저렴한 디스크의 복수 배열)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;말 그대로 RAID는 여러개의 디스크를 연결하여 가용성 보장하고, 비용을 절감하는 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 RAID는 어떤 종류가 있는지 알아보도록 하겠습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;RAID&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;RAID 0 _ Striping&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2784&quot; data-origin-height=&quot;1394&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ewSuHo/btsHB7jcslW/HrYKZS4yPz7wzO6Vd6qbPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ewSuHo/btsHB7jcslW/HrYKZS4yPz7wzO6Vd6qbPK/img.png&quot; data-alt=&quot;RAID 0&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ewSuHo/btsHB7jcslW/HrYKZS4yPz7wzO6Vd6qbPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FewSuHo%2FbtsHB7jcslW%2FHrYKZS4yPz7wzO6Vd6qbPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;705&quot; height=&quot;353&quot; data-origin-width=&quot;2784&quot; data-origin-height=&quot;1394&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;RAID 0&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;RAID 1 _ Mirroring&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2784&quot; data-origin-height=&quot;1392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/di8crt/btsHDyzVzV3/oRcpzV55RgBQrLdSCcyoR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/di8crt/btsHDyzVzV3/oRcpzV55RgBQrLdSCcyoR0/img.png&quot; data-alt=&quot;RAID 1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/di8crt/btsHDyzVzV3/oRcpzV55RgBQrLdSCcyoR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdi8crt%2FbtsHDyzVzV3%2FoRcpzV55RgBQrLdSCcyoR0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;658&quot; height=&quot;329&quot; data-origin-width=&quot;2784&quot; data-origin-height=&quot;1392&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;RAID 1&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;RAID 5 _ Striping with Parity&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2784&quot; data-origin-height=&quot;1416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/be9WNk/btsHDiYpuAK/WUVn2vNYgGKngBhWWlMuB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/be9WNk/btsHDiYpuAK/WUVn2vNYgGKngBhWWlMuB1/img.png&quot; data-alt=&quot;Striping with Parity&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/be9WNk/btsHDiYpuAK/WUVn2vNYgGKngBhWWlMuB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbe9WNk%2FbtsHDiYpuAK%2FWUVn2vNYgGKngBhWWlMuB1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;679&quot; height=&quot;345&quot; data-origin-width=&quot;2784&quot; data-origin-height=&quot;1416&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Striping with Parity&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패리티 비트란?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%ED%8C%A8%EB%A6%AC%ED%8B%B0_%EB%B9%84%ED%8A%B8&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ko.wikipedia.org/wiki/%ED%8C%A8%EB%A6%AC%ED%8B%B0_%EB%B9%84%ED%8A%B8&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1716727392340&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;패리티 비트 - 위키백과, 우리 모두의 백과사전&quot; data-og-description=&quot;위키백과, 우리 모두의 백과사전. 7 비트 데이터 패리티 포함 8 비트 짝수 홀수 0000000 (0) 00000000 10000000 1010001 (3) 11010001 01010001 1101001 (4) 01101001 11101001 1111111 (7) 11111111 01111111 패리티 비트(Parity bit)는 &quot; data-og-host=&quot;ko.wikipedia.org&quot; data-og-source-url=&quot;https://ko.wikipedia.org/wiki/%ED%8C%A8%EB%A6%AC%ED%8B%B0_%EB%B9%84%ED%8A%B8&quot; data-og-url=&quot;https://ko.wikipedia.org/wiki/%ED%8C%A8%EB%A6%AC%ED%8B%B0_%EB%B9%84%ED%8A%B8&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%ED%8C%A8%EB%A6%AC%ED%8B%B0_%EB%B9%84%ED%8A%B8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ko.wikipedia.org/wiki/%ED%8C%A8%EB%A6%AC%ED%8B%B0_%EB%B9%84%ED%8A%B8&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;패리티 비트 - 위키백과, 우리 모두의 백과사전&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;위키백과, 우리 모두의 백과사전. 7 비트 데이터 패리티 포함 8 비트 짝수 홀수 0000000 (0) 00000000 10000000 1010001 (3) 11010001 01010001 1101001 (4) 01101001 11101001 1111111 (7) 11111111 01111111 패리티 비트(Parity bit)는&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ko.wikipedia.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;RAID 6 _ Striping with Double Parity&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2784&quot; data-origin-height=&quot;1416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bksKJp/btsHDMENjr7/HRACuWdKHNFxsqAeRfQkz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bksKJp/btsHDMENjr7/HRACuWdKHNFxsqAeRfQkz1/img.png&quot; data-alt=&quot;Striping with Double Parity&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bksKJp/btsHDMENjr7/HRACuWdKHNFxsqAeRfQkz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbksKJp%2FbtsHDMENjr7%2FHRACuWdKHNFxsqAeRfQkz1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;738&quot; height=&quot;375&quot; data-origin-width=&quot;2784&quot; data-origin-height=&quot;1416&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Striping with Double Parity&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;++ RAID 방식&amp;nbsp;&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RAID 10 _ Mirroring + Striping&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RAID 50 _ Striping with Parity + Striping&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RAID 60 _ Striping with Double Parity + Striping&amp;nbsp;&lt;/p&gt;</description>
      <category>Kafka</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/7</guid>
      <comments>https://baektothefuture.tistory.com/7#entry7comment</comments>
      <pubDate>Sun, 26 May 2024 21:44:23 +0900</pubDate>
    </item>
    <item>
      <title>Elasticsearch_security 설정</title>
      <link>https://baektothefuture.tistory.com/5</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;파일 전송 방법&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;scp&lt;/b&gt; : ssh 원격 접속 프로토콜을 기반으로 한 파일 전송 프로토콜 -&amp;gt; 모든 노드에 배포해야 하기 때문
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용 방법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;scp [option] [filename] [remote id]@[remote ip]:[remote path] &amp;gt; 단일 파일을 원격지로 전송&lt;/li&gt;
&lt;li&gt;scp [option] [file 1] [file 2] ,,, [file N] [remote id]@[remote ip]:[remote path] &amp;gt; 복수의 파일을 원격지로 전송&lt;/li&gt;
&lt;li&gt;scp [option] [dic name] [remote id]@[remote ip]:[remote path] &amp;gt; 디렉터리를 원격지로 전송&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Filezilla&lt;/b&gt; : FTP 프로그램 중 하나 &amp;gt; FTP란? 파일전송 프로그램(File Transfer Protocol)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;파일 암호화 방식&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;X-Pack&lt;/b&gt; : Elasticsearch 에서 배포하는 공식 상용 플러그인&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;P12(Personal informaion Exchange File)&lt;/b&gt; : 암호화 키파일
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;바이너리 형식으로 저장, 포멧 파일은 인증서, 개인키 내용을 파일하나에 모두 담고 있다.&lt;/li&gt;
&lt;li&gt;백업용, 이동용으로 주로 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대칭키 방식&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동일한 키로 암호화, 복호화를 동시에 할 수 있는 방식&lt;/li&gt;
&lt;li&gt;대칭키 전달 과정에서 누군가가 대칭키를 획득한다면 쉽게 암호화된 데이터를 알아낼 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;공개키 방식 &lt;/b&gt;(대칭키 방식의 단점을 보완한 방식)&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공개키와 개인키(비밀키) 두개를 가지고 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공개키로 암호화를 하면 데이터 보안에 집중&lt;/li&gt;
&lt;li&gt;개인키로 암호화를 하면 인증 과정에 집중&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;992&quot; data-origin-height=&quot;1160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGR27p/btsHbmnSM4f/S00ZyHlElgVTk1cSQYSxKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGR27p/btsHbmnSM4f/S00ZyHlElgVTk1cSQYSxKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGR27p/btsHbmnSM4f/S00ZyHlElgVTk1cSQYSxKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGR27p%2FbtsHbmnSM4f%2FS00ZyHlElgVTk1cSQYSxKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;441&quot; height=&quot;1160&quot; data-origin-width=&quot;992&quot; data-origin-height=&quot;1160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;KeyStore&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;본인의 인증서 및 개인키 (Private Key)&lt;/li&gt;
&lt;li&gt;개인키들만 따로 모아서 만든 저장소&lt;/li&gt;
&lt;li&gt;생성방법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;bin/elasticsearch-certutil --ca [공개키 절대경로] -&amp;gt; 이름 미입력시 elastic-certificates.p12&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TrustStore&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;신뢰하는 상대방의 root ca 인증서 보관 (root ca란? -&amp;gt; 인증서를 발급해주는 기관 중 최상위 기관, 일반적으로 os에 내장되어 있음)&lt;/li&gt;
&lt;li&gt;공개키들만 따로 모아서 만든 저장소&lt;/li&gt;
&lt;li&gt;생성방법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;bin/elasticsearch-certutil ca --ca 의 이름 미입력 시 elasticsearch-ca.p12&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Elasticsearch</category>
      <category>Elasticsearch</category>
      <category>keystore</category>
      <category>truststore</category>
      <category>X-Pack</category>
      <category>보안설정</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/5</guid>
      <comments>https://baektothefuture.tistory.com/5#entry5comment</comments>
      <pubDate>Sun, 5 May 2024 16:02:54 +0900</pubDate>
    </item>
    <item>
      <title>Elasticsearch 8.12 설치 + 클러스터링 (리눅스)</title>
      <link>https://baektothefuture.tistory.com/4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;임시저장을 놓쳐 다시 쓰는 글.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;티스토리가 익숙치 않은지라 쓰던 글을 다 날렸네요 ㅎ ㅎ ㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;!&lt;/b&gt;&lt;/span&gt; 제정신이 아닐 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 elasticsearch를 설치 및 클러스터링을 구성했던것을 적어 보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저&amp;nbsp; Elasticsearch 설치 과정에 대해 설명하고..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 환경설정(yml 파일)에 대해 알아보며 클러스터링 과정을 적어보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후 한번 더 간다&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;u&gt;&lt;b&gt;Elasticsearch 설치&lt;/b&gt;&lt;/u&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설치 환경&lt;/b&gt; : Ubuntu&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설치 폴더&lt;/b&gt; : 원하는 위치에 설정 (mkdir /elastic)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설치(바이너리 파일)&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;*&lt;/span&gt;&lt;/b&gt; elasticsearch-8.12.0 버전으로 tar.gz 파일 다운&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(바이너리 파일 : 아이콘 우클릭 후 링크 주소 복사!)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;548&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5cLAH/btsG5kiEjkZ/zH4TkpKzNoP70O0bId8ii0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5cLAH/btsG5kiEjkZ/zH4TkpKzNoP70O0bId8ii0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5cLAH/btsG5kiEjkZ/zH4TkpKzNoP70O0bId8ii0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5cLAH%2FbtsG5kiEjkZ%2FzH4TkpKzNoP70O0bId8ii0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;190&quot; height=&quot;146&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;548&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;설치 명령어 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;i&gt;wget&amp;nbsp;&lt;a href=&quot;https://artifacts.elastic.co/downloads/elasticsearch-8.12.0-linux-x86_64.tar.gz&quot;&gt;https://artifacts.elastic.co/downloads/elasticsearch-8.12.0-linux-x86_64.tar.gz&lt;/a&gt;&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;해당 파일을 다운 받은 후 -&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;i&gt;&lt;b&gt;tar -xvf&lt;/b&gt;&lt;/i&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;를 통해 압축을 풀어줍니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;*&lt;/b&gt;&lt;/span&gt; 압축 해제 한 후 해당 설치파일 삭제&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;u&gt;&lt;b&gt;Elasticsearch 환경 설정&lt;/b&gt;&lt;/u&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노드 하나에 elasticsearch를 설치하고 운용할 경우 이는 개발모드라고 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 클러스터링을 하지 않으므로 따로 보안설정에 대해 설명하지 않겠습니다. (내맘임.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;elasticsearch는 yml 파일을 활용해 환경설정을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 파일은 config 폴더에 &lt;b&gt;elasticsearch.yml&lt;/b&gt;에 있으며 &lt;b&gt;vi 에디터를 활용하여 설정&lt;/b&gt;합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 single node, clustering 시 위 파일을 어떻게 설정했는지 약간의 설명과 함께 적어보도록 하겠습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;single node&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;cluster.name&lt;/b&gt; : 클러스터 이름 지정 (ex. cluster.name : node-1)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;node.name&lt;/b&gt; : node 이름 지정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;node.roles&lt;/b&gt; : node 권한 지정 -&amp;gt; 하나만 사용하므로 master와 data 노드 권한 모두 준다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;path.data&lt;/b&gt; : master 노드에서 관리하는 메타 데이터의 데이터 파일 경로&lt;/li&gt;
&lt;li&gt;&lt;b&gt;path.logs&lt;/b&gt; : log 파일 경로&lt;/li&gt;
&lt;li&gt;&lt;b&gt;bootstrap.memory_lock&lt;/b&gt; : elasticsearch는 jvm 환경에서 동작하므로 고정된 heap 메모리를 두어 다른 프로세스가 침범하지 못하게 막아준다. (boolean)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;network.host&lt;/b&gt; : node의 ip 설정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;http.port&lt;/b&gt; : elastiscsearch는 http 프로토콜을 통해 통신하므로 9200 ~ 9299 포트로 설정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;transport.port&lt;/b&gt; : elasticsearch는 tcp를 통해 노드끼리 통신하므로 9300 ~ 9299 포트로 설정&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;security 설정 (개발모드이므로 꺼놓을게요)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;xpack.security.enabled: false&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;xpack.security.enrollment.enabled: false&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;xpack.security.http.ssl:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;enabled : false&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;xpack.security.transport.ssl:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;enabled : false&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;실행 시 유의사항&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실행&lt;/b&gt; : bin 폴더의 elasticsearch&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; &lt;b&gt;&lt;i&gt;bin/elasticsearch&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Elasticsearch는 관리자 계정으로 실행하면 실행이 안되므로 새로운 user를 만들어 실행시킨다.(useradd 명령어를 통해 사용자 추가)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;*&lt;/span&gt; 로그 확인 &lt;span style=&quot;color: #ee2323;&quot;&gt;*&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[2024-05-01T10:59:47,966][INFO ][o.e.n.Node&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;] [single-node] initialized&lt;br /&gt;[2024-05-01T10:59:47,966][INFO ][o.e.n.Node&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;] [single-node] starting ...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 클러스터링에 대해 설명해보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;키보드를 바꿨더니 키감이 아주 좋군요&amp;nbsp;&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;계속 타자를 치고 싶습니다.&lt;/s&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Elasticsearch Clustering + Security 설정&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설치환경 : &lt;/b&gt;서버 3대&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 clustering 시 elasticsearch.yml 파일 설정 방법에 대해 알아보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;똑같은 elasticsearch.yml 파일 설정이라 크게 달라진 것은 없습니다만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클러스터링 시 오류를 유발할 수 있거나 부가적인 설명이 필요하다고 생각되는 필드만 다시 적어보도록 하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Clustering - elasticsearch.yml&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;cluster.name&lt;/b&gt; : 클러스터 이름 설정 -&amp;gt; 이름이 같지 않다면 같은 클러스터라고 인식하지 않는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;node.roles&lt;/b&gt; : 노드 역할 지정 -&amp;gt; 클러스터링 시 데이터 노드, 마스터 노드 등 역할을 지정해준다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;discovery.type&lt;/b&gt; : 다중 노드 클러스터를 형성할 지 여부를 지정 한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;discovery.type : multi-node&lt;/b&gt; -&amp;gt; 다른 노드가 클러스터에 join 할 수 있도록 허용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;discovery.type : single-node&lt;/b&gt; -&amp;gt; 개발모드&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;node.attr.&lt;i&gt;&amp;lt;rack_id&amp;gt;&lt;/i&gt;&lt;/b&gt; : 샤드를 여러 rack에 거쳐 분배하고 싶을 때 rack_id를 설정하여 분배&lt;/li&gt;
&lt;li&gt;&lt;b&gt;discovery.seed_hosts&lt;/b&gt; : 연결할 노드들의 ip, 클러스터 명(cluster.name)도 확인하므로 이름이 일치하는지 확인&lt;/li&gt;
&lt;li&gt;&lt;b&gt;cluster.initial_master_nodes&lt;/b&gt; : 마스터 후보 노드 지정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보안설정&lt;/b&gt;&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;security (&lt;i&gt;&lt;b&gt;bin/elasticsearch-certutil&lt;/b&gt;&lt;/i&gt;) &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;활성화&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;elasticsearch-certutil ca&lt;/b&gt; : 해당 명령어를 실행 후 받은 p12 파일을 모든 노드에 배포&lt;/li&gt;
&lt;li&gt;&lt;b&gt;elasticsearch-certutil cert --ca &amp;lt;ca.p12경로&amp;gt;&lt;/b&gt; : 모든 노드는 분배받은 ca.p12파일로 certificates.p12 파일을 생성&lt;/li&gt;
&lt;li&gt;&lt;u&gt;&lt;b&gt;certificates.p12를 config 폴더에 놓기 (필수)&lt;/b&gt;&lt;/u&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;xpack.security.enabled=true&lt;/b&gt;로 security 홝성화&lt;/li&gt;
&lt;li&gt;&lt;b&gt;xpack.security.transport.ssl.verification_mode&lt;/b&gt; : certificate&lt;/li&gt;
&lt;li&gt;&lt;b&gt;xpack.security.transport.ssl.keystore.path&lt;/b&gt; : certificates.p12&lt;/li&gt;
&lt;li&gt;&lt;b&gt;xpack.security.transport.ssl.trustore.path&lt;/b&gt; : certificates.p12&lt;/li&gt;
&lt;li&gt;&lt;b&gt;xpack.security.enrollment.enabled&lt;/b&gt; : true&lt;/li&gt;
&lt;li&gt;&lt;b&gt;xpack.security.authc.api__key.enabled&lt;/b&gt; : false -&amp;gt; API키를 활용하여 보안설정을 하는 방법&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1446&quot; data-origin-height=&quot;250&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/edmcQs/btsHcal9OjY/sOWi0RL0jno141Vf2mMDAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/edmcQs/btsHcal9OjY/sOWi0RL0jno141Vf2mMDAk/img.png&quot; data-alt=&quot;보안설정 예시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/edmcQs/btsHcal9OjY/sOWi0RL0jno141Vf2mMDAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FedmcQs%2FbtsHcal9OjY%2FsOWi0RL0jno141Vf2mMDAk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1446&quot; height=&quot;250&quot; data-origin-width=&quot;1446&quot; data-origin-height=&quot;250&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;보안설정 예시&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오류가 나왔다면 고려해봐야 하는 설정&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클러스터 이름이 동일한가?&lt;/li&gt;
&lt;li&gt;이름과 노드 역할 설정이 제대로 되어있나?&lt;/li&gt;
&lt;li&gt;위치 설정 : path, logs 파일 위치&lt;/li&gt;
&lt;li&gt;다른 프로세스가 elasticsearch 메모리에 접근 못하도록 방지 되어있나 ? : bootstrap.memory_lock&lt;/li&gt;
&lt;li&gt;discovery.seed_hosts에 연결되어야 할 노드의 ip가 제대로 작성되어 있는지&lt;/li&gt;
&lt;li&gt;vm 설정이 되어있는지 -&amp;gt; config/jvm.conf 에서 확인&lt;/li&gt;
&lt;li&gt;방화벽에 elasticseach가 사용하는 포트가 열려있는지&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글은 보안설정에 대해 조금 더 자세히 알아보도록 하겠습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(keystore이 뭔지 truststore이 뭔지,,)&lt;/p&gt;
&lt;figure id=&quot;og_1714993897303&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Elasticsearch_security 설정&quot; data-og-description=&quot;파일 전송 방법scp : ssh 원격 접속 프로토콜을 기반으로 한 파일 전송 프로토놀 &amp;gt; 모든 노드에 배포해야 하기 때문사용 방법scp [option] [filename] [remote id]@[remote ip]:[remote path] &amp;gt; 단일 파일을 원격지로 &quot; data-og-host=&quot;baektothefuture.tistory.com&quot; data-og-source-url=&quot;https://baektothefuture.tistory.com/5&quot; data-og-url=&quot;https://baektothefuture.tistory.com/5&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/e8Fit/hyV2v2IW4z/gYKrznE7kMx5YuqlkKHxzK/img.png?width=800&amp;amp;height=935&amp;amp;face=0_0_800_935,https://scrap.kakaocdn.net/dn/ckV7fY/hyV2Ek3JiY/kPo5u4dYWsh1K5ibpYAqoK/img.png?width=800&amp;amp;height=935&amp;amp;face=0_0_800_935,https://scrap.kakaocdn.net/dn/jU1aB/hyVZnZyIAv/2IxZOBf0EphLDpPyKcLKUK/img.png?width=992&amp;amp;height=1160&amp;amp;face=0_0_992_1160&quot;&gt;&lt;a href=&quot;https://baektothefuture.tistory.com/5&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://baektothefuture.tistory.com/5&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/e8Fit/hyV2v2IW4z/gYKrznE7kMx5YuqlkKHxzK/img.png?width=800&amp;amp;height=935&amp;amp;face=0_0_800_935,https://scrap.kakaocdn.net/dn/ckV7fY/hyV2Ek3JiY/kPo5u4dYWsh1K5ibpYAqoK/img.png?width=800&amp;amp;height=935&amp;amp;face=0_0_800_935,https://scrap.kakaocdn.net/dn/jU1aB/hyVZnZyIAv/2IxZOBf0EphLDpPyKcLKUK/img.png?width=992&amp;amp;height=1160&amp;amp;face=0_0_992_1160');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Elasticsearch_security 설정&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;파일 전송 방법scp : ssh 원격 접속 프로토콜을 기반으로 한 파일 전송 프로토놀 &amp;gt; 모든 노드에 배포해야 하기 때문사용 방법scp [option] [filename] [remote id]@[remote ip]:[remote path] &amp;gt; 단일 파일을 원격지로&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;baektothefuture.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Elasticsearch</category>
      <category>clustering</category>
      <category>Elasticsearch</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/4</guid>
      <comments>https://baektothefuture.tistory.com/4#entry4comment</comments>
      <pubDate>Sat, 4 May 2024 09:50:26 +0900</pubDate>
    </item>
    <item>
      <title>네트워크 기초</title>
      <link>https://baektothefuture.tistory.com/3</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;636&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YG6Ni/btsG0GFChJV/iRUPlwNLKR6Hzhi1SjfrGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YG6Ni/btsG0GFChJV/iRUPlwNLKR6Hzhi1SjfrGk/img.png&quot; data-alt=&quot;네트워크 계층&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YG6Ni/btsG0GFChJV/iRUPlwNLKR6Hzhi1SjfrGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYG6Ni%2FbtsG0GFChJV%2FiRUPlwNLKR6Hzhi1SjfrGk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;379&quot; height=&quot;464&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;636&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;네트워크 계층&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP/IP 4계층을 기준으로 네트워크에 대해 알아보겠습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저! 각 4계층에 대해 간략하게 설명하자면.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;애플리케이션 계층 : User(사용자) 영역
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특정 서비스를 제공하기 위해 애플리케이션 끼리 정보를 주고 받을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;전송 계층 : (S/W) Kernel 영역
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;송신된 데이터를 수신측 애플리케이션에 확실히 전달하게 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인터넷 계층 : &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;(S/W)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Kernel 영역
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;수신&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;링크 계층 : H/W 영역&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이라고 생각하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조금 더 자세히 각 계층에 대해 설명하자면 이와 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;애플리케이션 계층 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;User(사용자) 영역
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Socket&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;전송 계층 : (S/W) Kernel 영역
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Port&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인터넷 계층 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;(S/W)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Kernel 영역
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TCP/IP&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;링크 계층 : H/W 영역
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MAC&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;MAC&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MAC이란 물리적 네트워크 주소(하드웨어의 주소)로써 NIC(Network Interface Card)에 대한 식별자입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;225&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FG9ka/btsG0sU22rQ/oZHKs5ZvbF3wu2OCIfWGk0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FG9ka/btsG0sU22rQ/oZHKs5ZvbF3wu2OCIfWGk0/img.jpg&quot; data-alt=&quot;NIC&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FG9ka/btsG0sU22rQ/oZHKs5ZvbF3wu2OCIfWGk0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFG9ka%2FbtsG0sU22rQ%2FoZHKs5ZvbF3wu2OCIfWGk0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;225&quot; height=&quot;225&quot; data-origin-width=&quot;225&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;NIC&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(유선, 무선 두가지 방법을 통해 인터넷에 연결 할 수 있다면 NIC이 2개)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;IP 주소&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Host에 대한 식별자 (Host란 인터넷에 연결된 컴퓨터)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- NIC이 하나면 IP 하나? : Nope&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- NIC에 여러 IP를 Binding할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Port 번호&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램에 할당된 번호&lt;/p&gt;</description>
      <category>Network</category>
      <author>baektothefuture</author>
      <guid isPermaLink="true">https://baektothefuture.tistory.com/3</guid>
      <comments>https://baektothefuture.tistory.com/3#entry3comment</comments>
      <pubDate>Mon, 29 Apr 2024 21:02:51 +0900</pubDate>
    </item>
  </channel>
</rss>