<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: esga1102</title>
    <description>The latest articles on DEV Community by esga1102 (@esga1102).</description>
    <link>https://dev.to/esga1102</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1260480%2F287fac3c-1051-49ce-9860-b5b1674ad043.png</url>
      <title>DEV Community: esga1102</title>
      <link>https://dev.to/esga1102</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/esga1102"/>
    <language>en</language>
    <item>
      <title>Setup OpenSearch,Logstash,Kafka locally with Docker Compose (windows)</title>
      <dc:creator>esga1102</dc:creator>
      <pubDate>Thu, 17 Oct 2024 03:09:58 +0000</pubDate>
      <link>https://dev.to/esga1102/setup-opensearchlogstashkafka-locally-with-docker-compose-windows-2mi6</link>
      <guid>https://dev.to/esga1102/setup-opensearchlogstashkafka-locally-with-docker-compose-windows-2mi6</guid>
      <description>&lt;h2&gt;
  
  
  Directory tree
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  D:/
 -  opensearch
       + kafka
          - docker-compose.yaml
       + logstash
         + pipeline
            - input.conf
         - docker-compose.yaml
    - .env
    - docker-compose.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  opensearch
&lt;/h2&gt;

&lt;p&gt;add docker-compose file with content :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3'
services:
  opensearch-node1: # This is also the hostname of the container within the Docker network (i.e. https://opensearch-node1/)
    image: opensearchproject/opensearch:latest # Specifying the latest available image - modify if you want a specific version
    container_name: opensearch-node1
    environment:
      - cluster.name=opensearch-cluster # Name the cluster
      - node.name=opensearch-node1 # Name the node that will run in this container
      - discovery.seed_hosts=opensearch-node1,opensearch-node2 # Nodes to look for when discovering the cluster
      - cluster.initial_cluster_manager_nodes=opensearch-node1,opensearch-node2 # Nodes eligible to serve as cluster manager
      - bootstrap.memory_lock=true # Disable JVM heap memory swapping
      - "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m" # Set min and max JVM heap sizes to at least 50% of system RAM
      - OPENSEARCH_INITIAL_ADMIN_PASSWORD=${OPENSEARCH_INITIAL_ADMIN_PASSWORD}    # Sets the demo admin user password when using demo configuration, required for OpenSearch 2.12 and later
    ulimits:
      memlock:
        soft: -1 # Set memlock to unlimited (no soft or hard limit)
        hard: -1
      nofile:
        soft: 65536 # Maximum number of open files for the opensearch user - set to at least 65536
        hard: 65536
    volumes:
      - opensearch-data1:/usr/share/opensearch/data # Creates volume called opensearch-data1 and mounts it to the container
    ports:
      - 9200:9200 # REST API
      - 9600:9600 # Performance Analyzer
    networks:
      - opensearch-net # All of the containers will join the same Docker bridge network
  opensearch-node2:
    image: opensearchproject/opensearch:latest # This should be the same image used for opensearch-node1 to avoid issues
    container_name: opensearch-node2
    environment:
      - cluster.name=opensearch-cluster
      - node.name=opensearch-node2
      - discovery.seed_hosts=opensearch-node1,opensearch-node2
      - cluster.initial_cluster_manager_nodes=opensearch-node1,opensearch-node2
      - bootstrap.memory_lock=true
      - "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
      - OPENSEARCH_INITIAL_ADMIN_PASSWORD=${OPENSEARCH_INITIAL_ADMIN_PASSWORD}
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65536
        hard: 65536
    volumes:
      - opensearch-data2:/usr/share/opensearch/data
    networks:
      - opensearch-net
  opensearch-dashboards:
    image: opensearchproject/opensearch-dashboards:latest # Make sure the version of opensearch-dashboards matches the version of opensearch installed on other nodes
    container_name: opensearch-dashboards
    ports:
      - 5601:5601 # Map host port 5601 to container port 5601
    expose:
      - "5601" # Expose port 5601 for web access to OpenSearch Dashboards
    environment:
      OPENSEARCH_HOSTS: '["https://opensearch-node1:9200","https://opensearch-node2:9200"]' # Define the OpenSearch nodes that OpenSearch Dashboards will query
    networks:
      - opensearch-net
volumes:
  opensearch-data1:
  opensearch-data2:
networks:
  opensearch-net:
  kafka_opensearch-net:
    external: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then add .env file with your password :&lt;br&gt;
&lt;code&gt;OPENSEARCH_INITIAL_ADMIN_PASSWORD=mypassword1@2&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  kafka
&lt;/h2&gt;

&lt;p&gt;add docker-compose file with content :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3'

services:
  zookeeper:
    container_name: zookeeper-cntr
    image: confluentinc/cp-zookeeper:7.2.0
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000
    networks:
      - opensearch-net
  kafka:
    container_name: kafka-cntr
    image: confluentinc/cp-kafka:7.2.0
    depends_on:
      - zookeeper
    ports:
      - 29092:29092
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper-cntr:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka-cntr:9092,PLAINTEXT_HOST://localhost:29092
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_ADVERTISED_HOST_NAME: localhost
    networks:
      - opensearch-net
    healthcheck:
      test: nc -vz kafka-cntr 9092 || exit -1
      # start_period: 15s
      interval: 5s
      timeout: 10s
      retries: 10
networks:
  opensearch-net:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  logstash
&lt;/h2&gt;

&lt;p&gt;add docker-compose file with content :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3'

services:
  logstash:
    image: opensearchproject/logstash-oss-with-opensearch-output-plugin:8.4.0
    ports:
      - "5044:5044"
    expose:
      - "5044"
    volumes:
      - ./pipeline:/usr/share/logstash/pipeline
    networks:
      - opensearch_opensearch-net  
      - kafka_opensearch-net
networks:
  opensearch_opensearch-net:
    external: true
  kafka_opensearch-net:
    external: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  pipeline
&lt;/h3&gt;

&lt;p&gt;add input.conf file with content :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;input {
 kafka
    {
        bootstrap_servers =&amp;gt; "kafka-cntr:9092"
        topics =&amp;gt; "ServiceCentrallog"
        codec =&amp;gt; json
    }
}

filter {
    mutate {
      remove_field =&amp;gt; ["event"]
    }  
}
output {
  opensearch {
    hosts       =&amp;gt; ["https://opensearch-node1:9200"]
    user        =&amp;gt; "admin"
    password    =&amp;gt; "mypassword1@2"
    index       =&amp;gt; "service-centrallog-%{+YYYY.MM.dd}"
    ssl_certificate_verification =&amp;gt; false
    ecs_compatibility =&amp;gt; disabled
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 1 : Run opensearch docker-compose&lt;br&gt;
Step 2 : Run kafka docker-compose&lt;br&gt;
Step 3 : Run logtash after kafka has finished starting&lt;br&gt;
&lt;strong&gt;Local application can send log to kafka via: 127.0.0.1:29092&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;If opensearch fails to &lt;br&gt;
start : &lt;a href="https://stackoverflow.com/questions/51445846/elasticsearch-max-virtual-memory-areas-vm-max-map-count-65530-is-too-low-inc" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/51445846/elasticsearch-max-virtual-memory-areas-vm-max-map-count-65530-is-too-low-inc&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>programming</category>
      <category>elasticsearch</category>
      <category>logstash</category>
    </item>
    <item>
      <title>Oracle REST</title>
      <dc:creator>esga1102</dc:creator>
      <pubDate>Mon, 22 Jan 2024 15:51:14 +0000</pubDate>
      <link>https://dev.to/esga1102/oracle-rest-4ehh</link>
      <guid>https://dev.to/esga1102/oracle-rest-4ehh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Biến Oracle database thành một dịch vụ Restful API là một trong những tiện ích được ORACLE cung cấp dưới tên gọi ORDS (Oracle REST data service), là một dịch vụ REST API nhưng bản thân ORDS sẽ không thể thay thế hoàn toàn một web api server thực sự ( giao tiếp giữa các dịch vụ, xử dụng cache…), tuy nhiên ORDS vẫn có một số lợi thế nhất định trong phát triển ứng dụng web mà chúng ta có thể xem xét. &lt;/p&gt;

&lt;p&gt;Trên tư tưởng của API . Khi giải quyết các chủ đề kỹ thuật, thật dễ dàng để chỉ tập trung vào công nghệ. Nhưng sự phát triển ưu tiên API không chỉ là các tiêu chuẩn kỹ thuật. Đó là một cách làm việc và cộng tác. Thay vì chỉ quan tâm đến các chi tiết cụ thể của từng API, cách tiếp cận ưu tiên API thiên về việc xem xét các nhóm và hoạt động xung quanh các API đó của bạn. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  I.Oracle REST data service là gì?
&lt;/h1&gt;

&lt;p&gt;Oracle REST data service là một ứng dụng dạng mid-tier, ORDS sẽ cung cấp API theo tiêu chuẩn REST cho cơ sở dữ liệu Oracle. Với ORDS chúng ta có thể biến cơ sở dữ liệu Oracle thành dịch vụ API RESTful. Một mô hình triển khai thường sẽ như sau : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqviuychh9gft1b6mejrd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqviuychh9gft1b6mejrd.png" alt="Image description" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Trong hình ORDS sẽ đóng vai trò làm API web server để kết nối đến CSDL. ORDS chỉ chứa config và không giữ logic nghiệp vụ&lt;/li&gt;
&lt;li&gt; Logic nghiệp vụ lúc này sẽ chỉ nằm trên database.&lt;/li&gt;
&lt;li&gt; ORDS có thể kết nối đến nhiều CSDL.&lt;/li&gt;
&lt;li&gt; ORDS hỗ trợ authentication dựa trên OAuth2, một số tính năng được hỗ trợ :
 a. HTTP Basic Authentication
 b. API Key Authentication
 c. OAuth Authentication and Authorization
 d. Oracle Cloud Infrastructure Identity and Access Management (OCI IAM) with Identity Domains Authentication
 e. Oracle Identity Cloud Service (IDCS) Authentication&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  2 ORDS &amp;amp; API first &amp;amp; Database first
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Oracle REST data service là một công cụ ánh xạ trực tiếp giữa thiết kế database và API, linh hoạt cho nghiệp vụ doanh nghiệp. Bất kì thay đổi của cơ sở dữ liệu sẽ được cập nhật ngay cho dịch vụ API, điều này là một lợi thế rất lớn và nó đặc biệt hữu dụng trong trường hợp ứng dụng được phát triển dưới dạng chiến lược API (API First) song hành với Database First.&lt;/li&gt;
&lt;li&gt;Chiến lược ưu tiên API là lý tưởng cho kiến trúc vi dịch vụ vì chiến lược này đảm bảo hệ sinh thái ứng dụng bắt đầu dưới dạng hệ thống mô-đun và có thể tái sử dụng. Bằng cách nhấn mạnh các API từ sớm, cấu trúc của các yêu cầu và dữ liệu API được làm nổi bật. Điều này cho phép API cung cấp những gì nhà phát triển cần nhất và tránh dành thời gian của nhà phát triển cho các tính năng mà sau này hóa ra là không mong muốn. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2.1 Use case
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Mặc dù ORDS có thể phát triển ứng dụng REST API rất nhanh, nhưng bản thân nó cũng có một nhược điểm rất lớn. Hệ thống API bên ngoài có thể dễ dàng call API của ORDS nhưng không có chiều ngược lại, ORDS không được thiết kế để giao tiếp với server nào khác ngoài oracle database server&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2.1.1 Vì vậy hãy dùng ORDS khi
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  ORDS là tầng cung cấp dịch vụ dữ liệu ngoài cùng.&lt;/li&gt;
&lt;li&gt;  Là dịch vụ stateless và cô lập.&lt;/li&gt;
&lt;li&gt;  ORDS lý tưởng cho ứng dụng dạng database first. Đơn giản bởi vì khi thay thế nó bởi một hệ thống backend mạnh mẽ hơn, thì cũng không tốn chi phí cho việc test lại nghiệp vụ.&lt;/li&gt;
&lt;li&gt;  Có thể cân nhắc build-in tiến trình ORDS trong phát triển dịch vụ dạng low-code. &lt;/li&gt;
&lt;li&gt;  Trong trường hợp cần tích hợp với nhiều dịch vụ API, vẫn có thể sử dụng ORDS để tạo API logic nghiệp vụ cho các bên tích hợp trước cho đến khi hệ thống backend server được hoàn thành ( không bị duplicate công việc bởi ORDS không chứa code logic ).&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  3.Cách cấu hình ORDS
&lt;/h1&gt;

&lt;p&gt;Link : &lt;a href="https://www.oracle.com/database/technologies/appdev/rest-data-services-downloads-2043.html" rel="noopener noreferrer"&gt;https://www.oracle.com/database/technologies/appdev/rest-data-services-downloads-2043.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bước 1 : Run file ords, cấu hình theo các step như ảnh dưới&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffx51p0ld2e73zc3run30.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffx51p0ld2e73zc3run30.png" alt="Image description" width="800" height="815"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bước 2 : Enable Rest service trong Oracle Database&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwr4hngb6c8v0szrtnljd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwr4hngb6c8v0szrtnljd.png" alt="Image description" width="800" height="818"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bước 3: Tạo Rest module&lt;/p&gt;

&lt;p&gt;3.1 Rest module trong Rest data service&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fslli5lnxxwtym66x2c15.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fslli5lnxxwtym66x2c15.png" alt="Image description" width="308" height="892"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3.2 Tạo demo module và publish&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0matj7pnxhu2pc0dwvnl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0matj7pnxhu2pc0dwvnl.png" alt="Image description" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3.3 Tạo api trên module &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3m4huprbw41g6mlbsfoa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3m4huprbw41g6mlbsfoa.png" alt="Image description" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3.4 Kết quả&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfanf9qqb1udak6ycsgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfanf9qqb1udak6ycsgb.png" alt="Image description" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3.4 Xử lý logic nghiệp vụ bằng cách tạo 1 handler cho api vừa tạo&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chọn phương thức REST&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffuquzc94o6sepqt1vpkf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffuquzc94o6sepqt1vpkf.png" alt="Image description" width="420" height="178"&gt;&lt;/a&gt;&lt;br&gt;
3.5 Tạo logic và lưu kết quả &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkoj3r4acul71q2jya64h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkoj3r4acul71q2jya64h.png" alt="Image description" width="800" height="731"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Kết quả cuối cùng&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fejrzf0hvf43sfv5s569f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fejrzf0hvf43sfv5s569f.png" alt="Image description" width="800" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  4 Tính năng mở rộng
&lt;/h1&gt;

&lt;p&gt;Bên cạnh tính năng cấu hình làm REST service, ORDS cũng cung cấp giải pháp cho authentication, cache, HA … Chúng ta có thể xem hướng dẫn tại đây : &lt;br&gt;
&lt;a href="https://www.oracle.com/database/technologies/appdev/rest/best-practices/" rel="noopener noreferrer"&gt;https://www.oracle.com/database/technologies/appdev/rest/best-practices/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>oracle</category>
      <category>restapi</category>
    </item>
    <item>
      <title>Kafka KRaft Mode</title>
      <dc:creator>esga1102</dc:creator>
      <pubDate>Mon, 22 Jan 2024 15:36:34 +0000</pubDate>
      <link>https://dev.to/esga1102/kafka-kraft-mode-567f</link>
      <guid>https://dev.to/esga1102/kafka-kraft-mode-567f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Apache Kafka without Zookeeper&lt;/p&gt;

&lt;p&gt;Tài liệu này sẽ nói về Kafka ở chế độ KRAFT. KRAFT có ý nghĩa giờ đây Kafka sẽ tổ chức lại hoạt động của cluster dựa theo concept của thuật toán RAFT, lý do cho việc thay đổi này là do những hạn chế của Zookeeper trong các phiên bản cũ.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Về RAFT, RAFT là thuật toán đồng thuận được sử dụng phổ biến cho các hệ thống phân tán, một số hệ thống phổ biến :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RabbitMQsử dụng Raft để thay thế loại hang đợi mirror (replicated) sang quorum queue.&lt;/li&gt;
&lt;li&gt;MongoDBsử dụng một biến thể Raft trong replication set.&lt;/li&gt;
&lt;li&gt;SplunkEnterprise sử dụng Raft trong cơ chế Search Head Cluster (SHC)…v.v.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Với RAFT, đây là thuật toán rất thú vị trong tư tưởng về lập trình hệ thống phân tán. Tài liệu này không mô tả về RAFT tuy nhiên để tiếp cận nhanh nhất thuật toán này trong vài phút thì dưới đây là đường dẫn visualization mô phỏng thuật toán :&lt;br&gt;
&lt;a href="http://thesecretlivesofdata.com/raft/" rel="noopener noreferrer"&gt;http://thesecretlivesofdata.com/raft/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  1.Vấn đề của Zookeeper
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Zookeeper dường như là một phần không thể tách rời khi vận hành một hệ thống phân tán như Kafka nhưng nó có một số hạn chế khiến Kafka không thể phát huy hết khả năng của mình. Quy mô Kafka gặp phải bottleneck hiệu suất với Zookeeper&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hãy nhìn vào kiến trúc sau (hình ảnh từ confluence kafka):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7ybt32tvvw4lkwztj3n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7ybt32tvvw4lkwztj3n.png" alt="Image description" width="731" height="623"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kafka metadata : mô tả các borkers hiện có,thông tin về máy chủ và port . Đồng thời cung cấp thông tin về vị trí lưu trữ của borker host nào đang lưu trữ partition nào.&lt;/li&gt;
&lt;li&gt;Kafka controller: node đóng vai trò làm bộ điều khiển còn gọi là bộ điều khiển kafka&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;• Đối với mô hình Zookeeper trên, mỗi cụm có một node duy nhất đóng vai trò là bộ điều khiển (controller) được bầu chọn bởi những ZooKeeper watchers.&lt;br&gt;
• Nó lưu trữ partition logs, xử lý consume/produce giống như các broker khác và duy trì siêu dữ liệu cụm như ID broker, racks, topic, partition, leader, thông tin ISR(in-sync replicas) và cấu hình toàn cụm theo mỗi topic, cũng như thông tin đăng nhập bảo mật.&lt;br&gt;
• Kết quả là phần lớn lưu lượng đọc và ghi của ZooKeeper được thực hiện bởi node controller.&lt;br&gt;
• Controller đọc trạng thái của zookeeper và cập nhật metadata cho từng brokers một cách lần lượt và tuần tự. Zookeeper là nguồn metadata cho kafka, giữ thông tin trạng thái cụm kafka.&lt;br&gt;
• Giả sử một node trong cụm bị tắt dẫn đến metadata thay đổi, controller sẽ phải ghi lại metadata mới vào Zookeeper đồng thời controller sẽ update lần lượt metadata cho lần lượt từng borker, trong quá trình đó vấn đề ở đây  khi client cố gắng tìm kiếm leader bằng cách query thông tin từ broker client có khả năng sẽ không có câu trả lời, vì broker mà client đang tham khảo chưa được cập nhật lại thông tin trạng thái cụm.&lt;br&gt;
• Việc thiết lập cụm kafka sẽ phụ thuộc vào zookeeper, vấn đề lớn nhất ở đây là 2 hệ thống hoàn toàn khác biệt. Zookeeper là hệ thống bên ngoài kafka có nghĩa nó đi kèm với cú pháp tập lệnh điều khiển, cấu hình riêng của nó. Do đó khi bạn triển khai cụm cluster kafka bạn cũng phải quản lý, triển khai và giám sát Zookeeper.&lt;br&gt;
• Kafka &amp;amp; zookeeper triển khai 2 hệ thống sẽ không hiệu quả về mặt tài nguyên.&lt;br&gt;
• Với Zookeeper khả năng mở rộng của Kafka bị hạn chế. Mỗi khi khởi động cluster ,controller node Kafka phải tải trạng thái cluster từ Zookeeper, điều tương tự cũng xảy khi một Kafka broker tham gia vào cluster hoặc rời khỏi cluster , Zookeeper sẽ thực hiện lại việc bầu chọn leader, khi tiến trình này diễn ra Zookeeper sẽ làm chậm cụm (cluster), lượng metadata lớn dần theo thời gian dẫn đến việc tải lại metadata trở nên dần kém hiệu quả và làm hạn chế số lượng phân vùng mà cụm có thể lưu trữ theo confluent số lượng này tối đa là 200.000.&lt;br&gt;
• Để vượt qua các thách thức của Zookeeper ở Kafka , một KIP (Kafka improvement plan) đã được xuất bản đó là KIP-500 (&lt;a href="https://cwiki.apache.org/confluence/display/KAFKA/KIP-500%3A+Replace+ZooKeeper+with+a+Self-Managed+Metadata+Quorum" rel="noopener noreferrer"&gt;https://cwiki.apache.org/confluence/display/KAFKA/KIP-500%3A+Replace+ZooKeeper+with+a+Self-Managed+Metadata+Quorum&lt;/a&gt;). Trong phiên bản phát hành mới nhất , Zookeeper có thể được thay thế bằng một nhóm bộ điều khiển RAFT nội bộ. Bắt đầu từ phiên bản thử nghiệm 2.8.0 . Tuy nhiên cho đến khi phiên bản 4.0.0 phát hành trong tương lai thì các phiên bản hiện tại mới chỉ là bridge release.&lt;/p&gt;
&lt;h1&gt;
  
  
  2.Các thay đổi về kiến trúc cluster Kafka
&lt;/h1&gt;

&lt;p&gt;Hình ảnh dưới đây mô tả sự khác biệt giữa kiến trúc cũ và kiến trúc mới được khuyến nghị&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5rzm1a4u56x6f80anx4m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5rzm1a4u56x6f80anx4m.png" alt="Image description" width="731" height="419"&gt;&lt;/a&gt;&lt;br&gt;
• Trong kiến trúc được đề xuất, ba nút điều khiển thay thế cho ba nút ZooKeeper.&lt;br&gt;
• Trong kiến trúc cũ zoopkeeper , node controller sẽ phải chủ động update trạng thái cho các node broker trong cụm theo hướng mũi tên.&lt;br&gt;
• Giờ đây thay vì controller đưa ra các bản cập nhật cho các borker node, các borker node sẽ tự lấy metadata từ leader này . Trong các node controller , các node controller đang là follower (màu xanh) sẽ follow metadata từ controller leader (màu cam), tất cả controller sẽ cùng theo dõi trạng thái mới nhất metadata , điều này làm cho quá trình chuyển đổi dự phòng hầu như không bị tải lại metadata khi chuyển sang trạng thái mới. Cũng giống như Zookeeper, Raft yêu cầu phần lớn các node chạy để tiếp tục chạy, do đó cần tối thiểu 3 node cho một mô hình cụm cluster raft. &lt;br&gt;
Mặc dù các quy trình của controller tách biệt về mặt logic với các quy trình của borker, nhưng chúng không cần phải tách biệt về mặt vật lý&lt;/p&gt;
&lt;h1&gt;
  
  
  2.2 Mô hình triển khai
&lt;/h1&gt;

&lt;p&gt;Một cụm tối thiểu sẽ triển khai như sau :&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftguiuh23c8wvaaxk8vq3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftguiuh23c8wvaaxk8vq3.png" alt="Image description" width="731" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Các broker A và broker B sẽ lắng nghe event từ metadata topic , broker C leader sẽ là nguồn ghi event vào metadata topic. Khi leader C bị lỗi việc tải lại metadata sẽ không còn mất thời gian vì cả broker A và B đều đã có metadata trong bộ nhớ của nó. Ngoài ra Broker C có 1 một chu kì snapshot để hạn chế kích thước của metadata topic.&lt;/p&gt;

&lt;p&gt;Hình bên dưới là kiến trúc nếu ta triển khai tách biệt vai trò giữa các nút trong cụm.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0srqrxs4xzf3ttkq2jzq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0srqrxs4xzf3ttkq2jzq.png" alt="Image description" width="731" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;file setup docker-compose :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3'
networks:
  default:
    name: kafka_raft
services:
 kafka-1:
    image: bitnami/kafka:3.2.3
    container_name: kafka1
    hostname: node1
    user: root
    ports:
      - 19092:19092 #controller port
      - 9094:9094  
    environment:
      - KAFKA_BROKER_ID=1
      - KAFKA_CFG_NODE_ID=1
      - KAFKA_ENABLE_KRAFT=yes 
      - KAFKA_CFG_PROCESS_ROLES=controller,broker
      - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,CLIENT:PLAINTEXT
      - KAFKA_CFG_LISTENERS=CLIENT://0.0.0.0:9092,CONTROLLER://0.0.0.0:19092,EXTERNAL://:9094
      - KAFKA_CFG_ADVERTISED_LISTENERS=CLIENT://127.0.0.1:9092,EXTERNAL://127.0.0.1:9094
      - KAFKA_KRAFT_CLUSTER_ID=kkdhsaJUsdnnxjNNjjddtr  
      - ALLOW_PLAINTEXT_LISTENER=yes
      - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@node1:19092,2@node2:19093,3@node3:19094
      - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
      - KAFKA_CFG_BROKER_LISTENER_NAMES=PLAINTEXT
      - KAFKA_HEAP_OPTS=-Xmx256m -Xms256m
      - BITNAMI_DEBUG=true
      - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=CLIENT
 kafka-2:
    image: bitnami/kafka:3.2.3
    container_name: kafka2
    hostname: node2
    user: root
    ports:
      - 19093:19093 #external port controller
      - 9095:9095    
    environment:
      - KAFKA_BROKER_ID=2
      - KAFKA_CFG_NODE_ID=2
      - KAFKA_ENABLE_KRAFT=yes 
      - KAFKA_CFG_PROCESS_ROLES=controller,broker
      - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,CLIENT:PLAINTEXT
      - KAFKA_CFG_LISTENERS=CLIENT://0.0.0.0:9092,CONTROLLER://0.0.0.0:19093,EXTERNAL://0.0.0.0:9095
      - KAFKA_CFG_ADVERTISED_LISTENERS=CLIENT://127.0.0.1:9092,EXTERNAL://127.0.0.1:9095
      - KAFKA_KRAFT_CLUSTER_ID=kkdhsaJUsdnnxjNNjjddtr  
      - ALLOW_PLAINTEXT_LISTENER=yes
      - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@node1:19092,2@node2:19093,3@node3:19094
      - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
      - KAFKA_CFG_BROKER_LISTENER_NAMES=PLAINTEXT
      - KAFKA_HEAP_OPTS=-Xmx256m -Xms256m
      - BITNAMI_DEBUG=true
      - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=CLIENT
 kafka-3:
    image: bitnami/kafka:3.2.3
    container_name: kafka3
    hostname: node3
    user: root
    ports:
      - 19094:19094 #external port controller
      - 9096:9096  
    environment:
      - KAFKA_BROKER_ID=3
      - KAFKA_CFG_NODE_ID=3
      - KAFKA_ENABLE_KRAFT=yes 
      - KAFKA_CFG_PROCESS_ROLES=controller,broker
      - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,CLIENT:PLAINTEXT
      - KAFKA_CFG_LISTENERS=CLIENT://0.0.0.0:9092,CONTROLLER://0.0.0.0:19094,EXTERNAL://0.0.0.0:9096
      - KAFKA_CFG_ADVERTISED_LISTENERS=CLIENT://127.0.0.1:9092,EXTERNAL://127.0.0.1:9096
      - KAFKA_KRAFT_CLUSTER_ID=kkdhsaJUsdnnxjNNjjddtr  
      - ALLOW_PLAINTEXT_LISTENER=yes
      - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@node1:19092,2@node2:19093,3@node3:19094
      - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
      - KAFKA_CFG_BROKER_LISTENER_NAMES=PLAINTEXT
      - KAFKA_HEAP_OPTS=-Xmx256m -Xms256m
      - BITNAMI_DEBUG=true
      - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=CLIENT

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Cài đặt
&lt;/h1&gt;

&lt;p&gt;Run docker file với lệnh : docker-compose -f multi-node.yml up&lt;br&gt;
Bật cửa sổ cmd truy cập vào node để tạo topic thep các bước sau :&lt;/p&gt;

&lt;p&gt;Step 1. Chạy lệnh :&lt;br&gt;
docker exec -it kafka2 /bin/bash&lt;br&gt;
Step 2.Truy cập vào folder chứa tập lệnh điều khiển của kafka&lt;br&gt;
 cd /opt/bitnami/kafka/bin&lt;br&gt;
Step 3.Tạo topic trên 3 node của cụm&lt;br&gt;
 ./kafka-topics.sh --bootstrap-server localhost:9092 --create --topic worldcapitals --partitions 3 --replication-factor  3&lt;br&gt;
Kiểm tra thông tin topic vừa tạo:&lt;br&gt;
                 a.  ./kafka-topics.sh --bootstrap-server localhost:9092 --describe --topic worldcapitals&lt;br&gt;
Lúc này 3 phân vùng sẽ được tạo ra, mỗi phân vùng sẽ có bản sao ở các phân vùng còn lại&lt;/p&gt;

</description>
      <category>kafka</category>
    </item>
  </channel>
</rss>
