paint-brush
Hướng dẫn về Node.js: Cách xây dựng một ứng dụng hướng sự kiện đơn giản với Kafkatừ tác giả@alvinslee
Bài viết mới

Hướng dẫn về Node.js: Cách xây dựng một ứng dụng hướng sự kiện đơn giản với Kafka

từ tác giả Alvin Lee14m2024/06/28
Read on Terminal Reader

dài quá đọc không nổi

Tìm hiểu cách xây dựng một ứng dụng hướng sự kiện đơn giản bằng Node.js và Apache Kafka trên Heroku. Hướng dẫn này bao gồm việc thiết lập cụm Kafka, tạo ứng dụng Node.js để tạo và sử dụng các sự kiện cũng như triển khai ứng dụng trên Heroku. Cuối cùng, bạn sẽ có một ví dụ hoạt động về kiến trúc hướng sự kiện với khả năng xử lý dữ liệu theo thời gian thực.
featured image - Hướng dẫn về Node.js: Cách xây dựng một ứng dụng hướng sự kiện đơn giản với Kafka
Alvin Lee HackerNoon profile picture

Bạn đã bao giờ tự hỏi làm thế nào một số ứng dụng yêu thích của bạn xử lý các bản cập nhật theo thời gian thực chưa? Tỷ số thể thao trực tiếp, bảng giá thị trường chứng khoán hoặc thậm chí thông báo trên mạng xã hội — tất cả đều dựa vào kiến trúc hướng sự kiện (EDA) để xử lý dữ liệu ngay lập tức. EDA giống như một cuộc trò chuyện trong đó mọi thông tin mới đều gây ra phản hồi ngay lập tức. Đó là điều làm cho ứng dụng trở nên tương tác và phản hồi nhanh hơn.


Trong hướng dẫn này, chúng tôi sẽ hướng dẫn bạn xây dựng một ứng dụng hướng sự kiện đơn giản bằng cách sử dụng Apache Kafka trên Heroku. Chúng tôi sẽ bao gồm:

  • Thiết lập cụm Kafka trên Heroku


  • Xây dựng ứng dụng Node.js tạo và tiêu thụ các sự kiện


  • Triển khai ứng dụng của bạn lên Heroku


Apache Kafka là một công cụ mạnh mẽ để xây dựng hệ thống EDA. Đó là một nền tảng nguồn mở được thiết kế để xử lý các nguồn cấp dữ liệu theo thời gian thực. Apache Kafka trên Heroku là một tiện ích bổ sung Heroku cung cấp Kafka dưới dạng dịch vụ. Heroku giúp việc triển khai và quản lý ứng dụng khá dễ dàng và gần đây tôi đã sử dụng nó nhiều hơn trong các dự án của mình. Kết hợp Kafka với Heroku giúp đơn giản hóa quá trình thiết lập khi bạn muốn chạy một ứng dụng hướng sự kiện.


Đến cuối hướng dẫn này, bạn sẽ có một ứng dụng đang chạy thể hiện sức mạnh của EDA với Apache Kafka trên Heroku. Bắt đầu nào!

Bắt đầu

Trước khi đi sâu vào mã, hãy xem nhanh một số khái niệm cốt lõi. Một khi bạn hiểu những điều này, việc theo dõi sẽ dễ dàng hơn.


  • Sự kiện là những phần dữ liệu biểu thị một số sự kiện xảy ra trong hệ thống, chẳng hạn như kết quả đọc nhiệt độ từ cảm biến.


  • Chủ đề là các danh mục hoặc kênh nơi các sự kiện được xuất bản. Hãy coi chúng như những chủ đề bạn đăng ký trong một bản tin.


  • Nhà sản xuất là các thực thể tạo và gửi sự kiện đến các chủ đề. Trong ứng dụng EDA demo của chúng tôi, nhà sản xuất của chúng tôi sẽ là một bộ cảm biến thời tiết.


  • Người tiêu dùng là các thực thể đọc và xử lý các sự kiện từ các chủ đề. Ứng dụng của chúng tôi sẽ có một người tiêu dùng lắng nghe các sự kiện dữ liệu thời tiết và ghi lại chúng.

Giới thiệu về ứng dụng của chúng tôi

Chúng tôi sẽ xây dựng một ứng dụng Node.js bằng thư viện KafkaJS . Dưới đây là tổng quan nhanh về cách ứng dụng của chúng tôi sẽ hoạt động:


  1. Cảm biến thời tiết của chúng tôi (nhà sản xuất) sẽ tạo dữ liệu định kỳ - chẳng hạn như nhiệt độ, độ ẩm và áp suất khí quyển - và gửi những sự kiện này tới Apache Kafka. Đối với mục đích demo, dữ liệu sẽ được tạo ngẫu nhiên.


  2. Chúng tôi sẽ có một người tiêu dùng lắng nghe các chủ đề. Khi nhận được một sự kiện mới, nó sẽ ghi dữ liệu vào nhật ký.


  3. Chúng tôi sẽ triển khai toàn bộ thiết lập lên Heroku và sử dụng nhật ký Heroku để theo dõi các sự kiện khi chúng xảy ra.

Điều kiện tiên quyết

Trước khi chúng tôi bắt đầu, hãy đảm bảo bạn có những điều sau:


  • Tài khoản Heroku: Nếu bạn chưa có tài khoản, hãy đăng ký tại Heroku.
  • Heroku CLI: Tải xuống và cài đặt Heroku CLI.
  • Node.js được cài đặt trên máy cục bộ của bạn để phát triển. Trên máy của tôi, tôi đang sử dụng Node (v.20.9.0) và npm (10.4.0).


Cơ sở mã cho toàn bộ dự án này có sẵn trong kho GitHub này. Vui lòng sao chép mã và làm theo trong suốt bài đăng này.


Bây giờ chúng ta đã trình bày những điều cơ bản, hãy thiết lập cụm Kafka trên Heroku và bắt đầu xây dựng.

Thiết lập cụm Kafka trên Heroku

Hãy thiết lập mọi thứ trên Heroku. Đó là một quá trình khá nhanh chóng và dễ dàng.

Bước 1: Đăng nhập qua Heroku CLI

 ~/project$ heroku login

Bước 2: Tạo ứng dụng Heroku

 ~/project$ heroku create weather-eda


(Tôi đã đặt tên cho ứng dụng Heroku của mình weather-eda nhưng bạn có thể chọn một tên duy nhất cho ứng dụng của mình.)

Bước 3: Thêm Apache Kafka vào tiện ích bổ sung Heroku

 ~/project$ heroku addons:create heroku-kafka:basic-0 Creating heroku-kafka:basic-0 on ⬢ weather-eda... ~$0.139/hour (max $100/month) The cluster should be available in a few minutes. Run `heroku kafka:wait` to wait until the cluster is ready. You can read more about managing Kafka at https://devcenter.heroku.com/articles/kafka-on-heroku#managing-kafka kafka-adjacent-07560 is being created in the background. The app will restart when complete... Use heroku addons:info kafka-adjacent-07560 to check creation progress Use heroku addons:docs heroku-kafka to view documentation


Bạn có thể tìm thêm thông tin về tiện ích bổ sung Apache Kafka trên Heroku tại đây . Đối với bản demo của chúng tôi, tôi đang thêm cấp 0 Cơ bản của tiện ích bổ sung. Chi phí của tiện ích bổ sung là 0,139 USD/giờ. Khi tôi xây dựng ứng dụng demo này, tôi đã sử dụng tiện ích bổ sung này trong chưa đầy một giờ và sau đó tôi ngừng sử dụng nó.


Heroku phải mất vài phút để chuẩn bị Kafka và sẵn sàng cho bạn. Chẳng bao lâu nữa, đây là những gì bạn sẽ thấy:


 ~/project$ heroku addons:info kafka-adjacent-07560 === kafka-adjacent-07560 Attachments: weather-eda::KAFKA Installed at: Mon May 27 2024 11:44:37 GMT-0700 (Mountain Standard Time) Max Price: $100/month Owning app: weather-eda Plan: heroku-kafka:basic-0 Price: ~$0.139/hour State: created

Bước 4: Nhận thông tin xác thực và cấu hình Kafka

Khi cụm Kafka của chúng tôi được tạo ra, chúng tôi sẽ cần lấy thông tin xác thực và các cấu hình khác. Heroku tạo một số lọ cấu hình cho ứng dụng của chúng tôi, cung cấp cho chúng thông tin từ cụm Kafka vừa được tạo. Chúng ta có thể thấy tất cả các lọ cấu hình này bằng cách chạy như sau:


 ~/project$ heroku config === weather-eda Config Vars KAFKA_CLIENT_CERT: -----BEGIN CERTIFICATE----- MIIDQzCCAiugAwIBAgIBADANBgkqhkiG9w0BAQsFADAyMTAwLgYDVQQDDCdjYS1h ... -----END CERTIFICATE----- KAFKA_CLIENT_CERT_KEY: -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAsgv1oBiF4Az/IQsepHSh5pceL0XLy0uEAokD7ety9J0PTjj3 ... -----END RSA PRIVATE KEY----- KAFKA_PREFIX: columbia-68051. KAFKA_TRUSTED_CERT: -----BEGIN CERTIFICATE----- MIIDfzCCAmegAwIBAgIBADANBgkqhkiG9w0BAQsFADAyMTAwLgYDVQQDDCdjYS1h ... F+f3juViDqm4eLCZBAdoK/DnI4fFrNH3YzhAPdhoHOa8wi4= -----END CERTIFICATE----- KAFKA_URL: kafka+ssl://ec2-18-233-140-74.compute-1.amazonaws.com:9096,kafka+ssl://ec2-18-208-61-56.compute-1.amazonaws.com:9096...kafka+ssl://ec2-34-203-24-91.compute-1.amazonaws.com:9096


Như bạn có thể thấy, chúng tôi có một số biến cấu hình. Chúng tôi sẽ muốn có một tệp trong thư mục gốc dự án của chúng tôi có tên .env với tất cả các giá trị var cấu hình này. Để làm điều này, chúng ta chỉ cần chạy lệnh sau:


 ~/project$ heroku config --shell > .env


Tệp .env của chúng tôi trông như thế này:


 KAFKA_CLIENT_CERT="-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----" KAFKA_CLIENT_CERT_KEY="-----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY-----" KAFKA_PREFIX="columbia-68051." KAFKA_TRUSTED_CERT="-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----" KAFKA_URL="kafka+ssl://ec2-18-233-140-74.compute-1.amazonaws.com:9096,kafka+ssl://ec2-18-208-61-56.compute-1.amazonaws.com:9096...kafka+ssl://ec2-34-203-24-91.compute-1.amazonaws.com:9096"


Ngoài ra, chúng tôi đảm bảo thêm .env vào tệp .gitignore của mình. Chúng tôi không muốn đưa dữ liệu nhạy cảm này vào kho lưu trữ của mình.

Bước 5: Cài đặt Plugin Kafka vào Heroku CLI

Heroku CLI không có sẵn các lệnh liên quan đến Kafka. Vì chúng tôi đang sử dụng Kafka nên chúng tôi sẽ cần cài đặt plugin CLI .


 ~/project$ heroku plugins:install heroku-kafka Installing plugin heroku-kafka... installed v2.12.0


Bây giờ, chúng ta có thể quản lý cụm Kafka của mình từ CLI.


 ~/project$ heroku kafka:info === KAFKA_URL Plan: heroku-kafka:basic-0 Status: available Version: 2.8.2 Created: 2024-05-27T18:44:38.023+00:00 Topics: [··········] 0 / 40 topics, see heroku kafka:topics Prefix: columbia-68051. Partitions: [··········] 0 / 240 partition replicas (partitions × replication factor) Messages: 0 messages/s Traffic: 0 bytes/s in / 0 bytes/s out Data Size: [··········] 0 bytes / 4.00 GB (0.00%) Add-on: kafka-adjacent-07560 ~/project$ heroku kafka:topics === Kafka Topics on KAFKA_URL No topics found on this Kafka cluster. Use heroku kafka:topics:create to create a topic (limit 40)

Bước 6: Kiểm tra tương tác với cụm

Cũng như để kiểm tra sự tỉnh táo, hãy cùng thử nghiệm với cụm Kafka của chúng tôi. Chúng tôi bắt đầu bằng cách tạo một chủ đề.


 ~/project$ heroku kafka:topics:create test-topic-01 Creating topic test-topic-01 with compaction disabled and retention time 1 day on kafka-adjacent-07560... done Use `heroku kafka:topics:info test-topic-01` to monitor your topic. Your topic is using the prefix columbia-68051.. ~/project$ heroku kafka:topics:info test-topic-01 ▸ topic test-topic-01 is not available yet


Trong vòng một phút hoặc lâu hơn, chủ đề của chúng tôi sẽ có sẵn.


 ~/project$ heroku kafka:topics:info test-topic-01 === kafka-adjacent-07560 :: test-topic-01 Topic Prefix: columbia-68051. Producers: 0 messages/second (0 bytes/second) total Consumers: 0 bytes/second total Partitions: 8 partitions Replication Factor: 3 Compaction: Compaction is disabled for test-topic-01 Retention: 24 hours


Tiếp theo, trong cửa sổ terminal này, chúng ta sẽ đóng vai trò là người tiêu dùng, lắng nghe chủ đề này bằng cách theo dõi nó.


 ~/project$ heroku kafka:topics:tail test-topic-01


Từ đây, thiết bị đầu cuối chỉ cần chờ bất kỳ sự kiện nào được xuất bản về chủ đề này.


Trong một cửa sổ terminal riêng biệt, chúng tôi sẽ đóng vai trò là nhà sản xuất và sẽ xuất bản một số thông báo về chủ đề này.


 ~/project$ heroku kafka:topics:write test-topic-01 "hello world!"


Quay lại cửa sổ terminal của người tiêu dùng, đây là những gì chúng ta thấy:


 ~/project$ heroku kafka:topics:tail test-topic-01 test-topic-01 0 0 12 hello world!


Xuất sắc! Chúng tôi đã sản xuất và sử dụng thành công một sự kiện cho một chủ đề trong cụm Kafka của mình. Chúng ta đã sẵn sàng chuyển sang ứng dụng Node.js của mình. Hãy hủy bỏ chủ đề kiểm tra này để giữ cho sân chơi của chúng ta luôn ngăn nắp.


 ~/project$ heroku kafka:topics:destroy test-topic-01 ▸ This command will affect the cluster: kafka-adjacent-07560, which is on weather-eda ▸ To proceed, type weather-eda or re-run this command with --confirm weather-eda > weather-eda Deleting topic test-topic-01... done Your topic has been marked for deletion, and will be removed from the cluster shortly ~/project$ heroku kafka:topics === Kafka Topics on KAFKA_URL No topics found on this Kafka cluster. Use heroku kafka:topics:create to create a topic (limit 40).

Bước 7: Chuẩn bị Kafka cho Ứng dụng của chúng tôi

Để chuẩn bị cho ứng dụng sử dụng Kafka của chúng tôi, chúng tôi sẽ cần tạo hai thứ: một chủ đề và một nhóm người tiêu dùng.


Hãy tạo chủ đề mà ứng dụng của chúng tôi sẽ sử dụng.


 ~/project$ heroku kafka:topics:create weather-data


Tiếp theo, chúng ta sẽ tạo nhóm người tiêu dùng mà người tiêu dùng ứng dụng của chúng ta sẽ là một phần trong đó:


 ~/project$ heroku kafka:consumer-groups:create weather-consumers


Chúng tôi đã sẵn sàng xây dựng ứng dụng Node.js của mình!

Xây dựng ứng dụng

Hãy khởi tạo một dự án mới và cài đặt các phần phụ thuộc của chúng ta.


 ~/project$ npm init -y ~/project$ npm install kafkajs dotenv @faker-js/faker pino pino-pretty


Dự án của chúng tôi sẽ có hai quy trình đang chạy:


  1. consumer.js , được đăng ký chủ đề và ghi lại bất kỳ sự kiện nào được xuất bản.


  2. producer.js , sẽ xuất bản một số dữ liệu thời tiết ngẫu nhiên về chủ đề này cứ sau vài giây.


Cả hai quy trình này sẽ cần sử dụng KafkaJS để kết nối với cụm Kafka của chúng tôi, vì vậy chúng tôi sẽ mô-đun hóa mã của mình để mã có thể sử dụng lại được.

Làm việc với khách hàng Kafka

Trong thư mục src của dự án, chúng ta tạo một tệp có tên kafka.js . Nó trông như thế này:


 const { Kafka } = require('kafkajs'); const BROKER_URLS = process.env.KAFKA_URL.split(',').map(uri => uri.replace('kafka+ssl://','' )) const TOPIC = `${process.env.KAFKA_PREFIX}weather-data` const CONSUMER_GROUP = `${process.env.KAFKA_PREFIX}weather-consumers` const kafka = new Kafka({ clientId: 'weather-eda-app-nodejs-client', brokers: BROKER_URLS, ssl: { rejectUnauthorized: false, ca: process.env.KAFKA_TRUSTED_CERT, key: process.env.KAFKA_CLIENT_CERT_KEY, cert: process.env.KAFKA_CLIENT_CERT, }, }) const producer = async () => { const p = kafka.producer() await p.connect() return p; } const consumer = async () => { const c = kafka.consumer({ groupId: CONSUMER_GROUP, sessionTimeout: 30000 }) await c.connect() await c.subscribe({ topics: [TOPIC] }); return c; } module.exports = { producer, consumer, topic: TOPIC, groupId: CONSUMER_GROUP };


Trong tệp này, chúng tôi bắt đầu bằng cách tạo một ứng dụng khách Kafka mới. Điều này yêu cầu URL cho các nhà môi giới Kafka mà chúng tôi có thể phân tích cú pháp từ biến KAFKA_URL trong tệp .env của chúng tôi (ban đầu xuất phát từ việc gọi cấu hình heroku). Để xác thực nỗ lực kết nối, chúng tôi cần cung cấp KAFKA_TRUSTED_CERT , KAFKA_CLIENT_CERT_KEYKAFKA_CLIENT_CERT .


Sau đó, từ ứng dụng khách Kafka của chúng tôi, chúng tôi tạo ra một producer và một consumer , đảm bảo đăng ký người tiêu dùng của chúng tôi với chủ đề weather-data .

Làm rõ về tiền tố Kafka

Lưu ý trong kafka.js rằng chúng tôi thêm KAFKA_PREFIX vào tên chủ đề và nhóm người tiêu dùng của chúng tôi. Chúng tôi đang sử dụng gói Basic 0 cho Apache Kafka trên Heroku, đây là gói Kafka có nhiều người thuê. Điều này có nghĩa là chúng tôi làm việc với KAFKA_PREFIX . Mặc dù chúng tôi đã đặt tên chủ đề là weather-data và nhóm người tiêu dùng weather-consumers , tên thực tế của chúng trong cụm Kafka nhiều người thuê của chúng tôi phải có KAFKA_PREFIX thêm vào trước (để đảm bảo chúng là duy nhất).


Vì vậy, về mặt kỹ thuật, đối với bản demo của chúng tôi, tên chủ đề thực tế là columbia-68051.weather-data , không phải weather-data . (Tương tự như vậy đối với tên nhóm người tiêu dùng.)

Quy trình sản xuất

Bây giờ, hãy tạo quy trình nền sẽ đóng vai trò là nhà sản xuất cảm biến thời tiết. Trong thư mục gốc dự án của chúng tôi, chúng tôi có một tệp có tên là producer.js . Nó trông như thế này:


 require('dotenv').config(); const kafka = require('./src/kafka.js'); const { faker } = require('@faker-js/faker'); const SENSORS = ['sensor01','sensor02','sensor03','sensor04','sensor05']; const MAX_DELAY_MS = 20000; const READINGS = ['temperature','humidity','barometric_pressure']; const MAX_TEMP = 130; const MIN_PRESSURE = 2910; const PRESSURE_RANGE = 160; const getRandom = (arr) => arr[faker.number.int(arr.length - 1)]; const getRandomReading = { temperature: () => faker.number.int(MAX_TEMP) + (faker.number.int(100) / 100), humidity: () => faker.number.int(100) / 100, barometric_pressure: () => (MIN_PRESSURE + faker.number.int(PRESSURE_RANGE)) / 100 }; const sleep = (ms) => { return new Promise((resolve) => { setTimeout(resolve, ms); }); }; (async () => { const producer = await kafka.producer() while(true) { const sensor = getRandom(SENSORS) const reading = getRandom(READINGS) const value = getRandomReading[reading]() const data = { reading, value } await producer.send({ topic: kafka.topic, messages: [{ key: sensor, value: JSON.stringify(data) }] }) await sleep(faker.number.int(MAX_DELAY_MS)) } })()


Rất nhiều mã trong tệp liên quan đến việc tạo ra các giá trị ngẫu nhiên. Tôi sẽ nhấn mạnh những phần quan trọng:


  • Chúng ta sẽ mô phỏng việc có năm cảm biến thời tiết khác nhau. Tên của họ được tìm thấy trong SENSORS .


  • Một cảm biến sẽ phát ra (xuất bản) một giá trị cho một trong ba giá trị có thể đọc được: temperature , humidity hoặc barometric_pressure . Đối tượng getRandomReading có chức năng cho mỗi lần đọc này để tạo ra giá trị tương ứng hợp lý.


  • Toàn bộ quá trình chạy như một hàm async với vòng lặp while vô hạn.


Trong vòng lặp while , chúng ta:


  • Chọn ngẫu nhiên một sensor .
  • Chọn một reading ngẫu nhiên.
  • Tạo một value ngẫu nhiên cho lần đọc đó.
  • Gọi producer.send để xuất bản dữ liệu này vào chủ đề. sensor đóng vai trò là key cho sự kiện, trong khi việc readingvalue sẽ tạo thành thông báo sự kiện.
  • Sau đó, chúng tôi đợi tối đa 20 giây trước khi lặp lại vòng lặp tiếp theo.

Quy trình tiêu dùng

Quá trình nền trong consumer.js đơn giản hơn đáng kể.


 require('dotenv').config(); const logger = require('./src/logger.js'); const kafka = require('./src/kafka.js'); (async () => { const consumer = await kafka.consumer() await consumer.run({ eachMessage: async ({ topic, partition, message }) => { const sensorId = message.key.toString() const messageObj = JSON.parse(message.value.toString()) const logMessage = { sensorId } logMessage[messageObj.reading] = messageObj.value logger.info(logMessage) } }) })()


consumer của chúng tôi đã đăng ký chủ đề weather-data . Chúng ta gọi consumer.run và sau đó thiết lập một trình xử lý cho eachMessage . Bất cứ khi nào Kafka thông báo cho consumer về một tin nhắn, nó sẽ ghi lại tin nhắn đó. Thats tất cả để có nó.

Quy trình và Procfile

Trong tệp package.json , chúng ta cần thêm một vài scripts để khởi động các quy trình nền của nhà sản xuất và người tiêu dùng. Tệp bây giờ sẽ bao gồm những nội dung sau:


 ... "scripts": { "start": "echo 'do nothing'", "start:consumer": "node consumer.js", "start:producer": "node producer.js" }, ...


Những cái quan trọng là start:consumerstart:producer . Nhưng chúng tôi vẫn start trong tệp của mình (mặc dù nó không có ý nghĩa gì) vì trình tạo Heroku mong đợi nó ở đó.


Tiếp theo, chúng tôi tạo một Procfile sẽ cho Heroku biết cách khởi động các công nhân khác nhau mà chúng tôi cần cho ứng dụng Heroku của mình. Trong thư mục gốc của dự án của chúng ta, Procfile sẽ trông như thế này:


 consumer_worker: npm run start:consumer producer_worker: npm run start:producer


Khá đơn giản phải không? Chúng ta sẽ có một nhân viên xử lý nền được gọi là consumer_worker và một nhân viên khác được gọi là producer_worker . Bạn sẽ nhận thấy rằng chúng tôi không có nhân viên web , đây là những gì bạn thường thấy trong Procfile dành cho ứng dụng web. Đối với ứng dụng Heroku của chúng tôi, chúng tôi chỉ cần hai nhân viên nền. Chúng tôi không cần web .

Triển khai và thử nghiệm ứng dụng

Cùng với đó, tất cả mã của chúng tôi đã được thiết lập. Chúng tôi đã đưa tất cả mã của mình vào kho lưu trữ và sẵn sàng triển khai.


 ~/project$ git push heroku main … remote: -----> Build succeeded! … remote: -----> Compressing... remote: Done: 48.6M remote: -----> Launching... … remote: Verifying deploy... done


Sau khi triển khai, chúng tôi muốn đảm bảo rằng chúng tôi mở rộng quy mô dynos đúng cách. Chúng tôi không cần dyno cho quy trình web, nhưng chúng tôi sẽ cần một dyno cho cả consumer_workerproducer_worker . Chúng tôi chạy lệnh sau để thiết lập các quy trình này dựa trên nhu cầu của chúng tôi.


 ~/project$ heroku ps:scale web=0 consumer_worker=1 producer_worker=1 Scaling dynos... done, now running producer_worker at 1:Eco, consumer_worker at 1:Eco, web at 0:Eco


Bây giờ, mọi thứ sẽ được thiết lập và chạy. Đằng sau hậu trường, producer_worker của chúng tôi sẽ kết nối với cụm Kafka và sau đó bắt đầu xuất bản dữ liệu cảm biến thời tiết cứ sau vài giây. Sau đó, consumer_worker của chúng ta sẽ kết nối với cụm Kafka và ghi lại mọi tin nhắn mà nó nhận được từ chủ đề mà nó đã đăng ký.


Để xem consumer_worker của chúng ta đang làm gì, chúng ta có thể xem nhật ký Heroku của mình.


 ~/project$ heroku logs --tail … heroku[producer_worker.1]: Starting process with command `npm run start:producer` heroku[producer_worker.1]: State changed from starting to up app[producer_worker.1]: app[producer_worker.1]: > [email protected] start:producer app[producer_worker.1]: > node producer.js app[producer_worker.1]: … heroku[consumer_worker.1]: Starting process with command `npm run start:consumer` heroku[consumer_worker.1]: State changed from starting to up app[consumer_worker.1]: app[consumer_worker.1]: > [email protected] start:consumer app[consumer_worker.1]: > node consumer.js app[consumer_worker.1]: app[consumer_worker.1]: {"level":"INFO","timestamp":"2024-05-28T02:31:20.660Z","logger":"kafkajs","message":"[Consumer] Starting","groupId":"columbia-68051.weather-consumers"} app[consumer_worker.1]: {"level":"INFO","timestamp":"2024-05-28T02:31:23.702Z","logger":"kafkajs","message":"[ConsumerGroup] Consumer has joined the group","groupId":"columbia-68051.weather-consumers","memberId":"weather-eda-app-nodejs-client-3ee5d1fa-eba9-4b59-826c-d3b924a6e4e4","leaderId":"weather-eda-app-nodejs-client-3ee5d1fa-eba9-4b59-826c-d3b924a6e4e4","isLeader":true,"memberAssignment":{"columbia-68051.test-topic-1":[0,1,2,3,4,5,6,7]},"groupProtocol":"RoundRobinAssigner","duration":3041} app[consumer_worker.1]: [2024-05-28 02:31:23.755 +0000] INFO (21): {"sensorId":"sensor01","temperature":87.84} app[consumer_worker.1]: [2024-05-28 02:31:23.764 +0000] INFO (21): {"sensorId":"sensor01","humidity":0.3} app[consumer_worker.1]: [2024-05-28 02:31:23.777 +0000] INFO (21): {"sensorId":"sensor03","temperature":22.11} app[consumer_worker.1]: [2024-05-28 02:31:37.773 +0000] INFO (21): {"sensorId":"sensor01","barometric_pressure":29.71} app[consumer_worker.1]: [2024-05-28 02:31:54.495 +0000] INFO (21): {"sensorId":"sensor05","barometric_pressure":29.55} app[consumer_worker.1]: [2024-05-28 02:32:02.629 +0000] INFO (21): {"sensorId":"sensor04","temperature":90.58} app[consumer_worker.1]: [2024-05-28 02:32:03.995 +0000] INFO (21): {"sensorId":"sensor02","barometric_pressure":29.25} app[consumer_worker.1]: [2024-05-28 02:32:12.688 +0000] INFO (21): {"sensorId":"sensor04","humidity":0.1} app[consumer_worker.1]: [2024-05-28 02:32:32.127 +0000] INFO (21): {"sensorId":"sensor01","humidity":0.34} app[consumer_worker.1]: [2024-05-28 02:32:32.851 +0000] INFO (21): {"sensorId":"sensor02","humidity":0.61} app[consumer_worker.1]: [2024-05-28 02:32:37.200 +0000] INFO (21): {"sensorId":"sensor01","barometric_pressure":30.36} app[consumer_worker.1]: [2024-05-28 02:32:50.388 +0000] INFO (21): {"sensorId":"sensor03","temperature":104.55}


Nó hoạt động! Chúng tôi biết rằng nhà sản xuất của chúng tôi định kỳ xuất bản tin nhắn tới Kafka vì người tiêu dùng của chúng tôi nhận được chúng và sau đó ghi lại chúng.


Tất nhiên, trong một ứng dụng EDA lớn hơn, mọi cảm biến đều là nhà sản xuất. Họ có thể xuất bản về nhiều chủ đề cho nhiều mục đích khác nhau hoặc tất cả đều có thể xuất bản về cùng một chủ đề. Và người tiêu dùng của bạn có thể đăng ký nhiều chủ đề. Ngoài ra, trong ứng dụng demo của chúng tôi, người tiêu dùng của chúng tôi chỉ đơn giản đưa ra rất nhiều thông tin trên eachMessage ; nhưng trong ứng dụng EDA, người tiêu dùng có thể phản hồi bằng cách gọi API của bên thứ ba, gửi thông báo SMS hoặc truy vấn cơ sở dữ liệu.


Bây giờ bạn đã hiểu cơ bản về các sự kiện, chủ đề, nhà sản xuất và người tiêu dùng cũng như biết cách làm việc với Kafka, bạn có thể bắt đầu thiết kế và xây dựng các ứng dụng EDA của riêng mình để đáp ứng các trường hợp sử dụng kinh doanh phức tạp hơn.

Phần kết luận

EDA khá mạnh mẽ — bạn có thể tách rời hệ thống của mình trong khi tận hưởng các tính năng chính như khả năng mở rộng dễ dàng và xử lý dữ liệu theo thời gian thực. Đối với EDA, Kafka là công cụ quan trọng, giúp bạn xử lý các luồng dữ liệu thông lượng cao một cách dễ dàng. Sử dụng Apache Kafka trên Heroku giúp bạn bắt đầu nhanh chóng. Vì đây là dịch vụ được quản lý nên bạn không cần phải lo lắng về các phần phức tạp trong quản lý cụm Kafka. Bạn chỉ có thể tập trung vào việc xây dựng ứng dụng của mình.


Từ đây, đã đến lúc bạn thử nghiệm và tạo nguyên mẫu. Xác định trường hợp sử dụng nào phù hợp với EDA. Hãy tham gia, thử nghiệm nó trên Heroku và tạo ra thứ gì đó tuyệt vời. Chúc mừng mã hóa!