DDD - Project: vetautet.com 07: Cơn ác mộng của việc tìm kiếm log và cuộc cách mạng trong DDD project

Nội dung bài viết

Video học lập trình mỗi ngày

Bài viết này được đưa vào Series: Dự án DDD - vetautet.com có lượng đồng thời CAO

Nếu bạn là một thành viên mới trong dự án DDD - vetautet.com

Hãy bỏ qua nếu bạn đã là thành viên cũ...

Vân như thường lệ chúng ta dành một góc nhỏ là dành cho những lập trình viên lần đầu ghé qua Series này. Hãy để tôi tóm tắt một chút về các phần trước, nói chung là từ một dev intern thì chúng ta phải đi từ đâu, và điều kiện là gì? công nghệ, ngôn ngữ, kỹ năng nào được hình thành thông qua các phần thực hành sau đây.

01 - SpringBoot 3: CÁCH xây dựng dự án triển khai về DDD bán VÉ TÀU, MUSIC với kiến trúc đồng thời CAO!

02 - Chúng tôi xây dựng Structure DDD Project như thế nào đạt chuẩn?

03 - Không tranh cãi, chúng tôi thống nhất hoàn thành kiến trúc DDD này

04 - Khi publish API chúng tôi gặp lượng request rất nhiều, áp dụng Circuit Breaker vs RateLimiter

05 - Sếp bảo tăng tốc từ 1000 lên 10.000 req/s, chúng tôi quyết định thêm Distributed Cached

06 - Sếp - Tại sao chúng ta không sử dụng LUA Redis mà chọn Redisson cho chức năng Lock

07 - Sếp ơi, làm ơn đừng gọi em nửa đêm nữa, chúng tôi đã thiết lập giám sát hệ thống Prometheus vs Grafana

08 - Chúng tôi đã thiết lập giám sát Database thông qua Prometheus vs Grafana, giờ ngủ ngon rồi

09 - Thiết lập giám sát Redis thông qua Prometheus vs Grafana và chuẩn bị thiết lập 20.000 req/s

10 - Chuẩn bị có việc tăng tốc từ 10.000 lên 20.000 req/s không tăng chi phí

11 - Sếp cảm ơn anh em vì hoàn thành việc tăng tốc từ 10.000 lên 20.000 req/s nhưng team đối mắt với vấn đề khác

12 - ELK - Một khi bạn quản lý Log không được hãy sử dụng Kibana, logstash và elasticsearch

13 - Tại sao số lượng vé tàu lại cập nhật không đúng?

Trên đó là những video triển khai bằng code dành cho trường thợp thực tế của các hệ thống có tính đồng thời cao.

Còn nếu như bạn đã có kinh nghiệm và không cần chuyện thực hành thì có thể đọc câu chuyện này tại blog anonystick.com, vào mỗi cuối tuần tôi sẽ tóm tắt những thứ mà chúng tôi gặp phải trong lúc phát triển dự án.

01 - DDD - Project: vetautet.com 01: Triển Khai Kiến Trúc DDD Cho Ứng Dụng Bán Vé Tàu Tết Với Spring Boot Phần 1: Giới Thiệu Cấu Trúc Module

01 - DDD - Project: vetautet.com 02: Tuyến phỏng thủ đầu tiên được thiếp lập

01 - DDD - Project: vetautet.com 03: Tuyến phỏng thủ thứ hai của lập trình viên nhiều kinh nghiệm

04 - DDD - Project: vetautet.com 04: Một tai nạn trực tuyến xảy ra lúc 11h đêm, một cuộc điện thoại và nhiều notifications

05 - DDD - Project: vetautet.com 05: Hệ thống chúng tôi cảm ơn thằng em INTERN và đây có lẽ là định mệnh

06 - DDD - Project: vetautet.com 06: INTERN với sự khiêm tốn đến kỳ lạ lần này nó đã thực sự thành công lên Junior

07 - DDD - Project: vetautet.com 07: Log quá nhiều đến lúc chúng tôi phải thêm chi phí quản lý nhật ký của hệ thống - Bài viết này...

Cơn ác mộng của việc tìm kiếm log DDD project

Đó là ngày đầu tiên của tôi sau khi được tăng chức khi có một bước tiến mới trong việc Cải thiện hiệu suất API mới kỹ thuật mới trong DDD - Project với tư cách một Junior tại một công ty công nghệ. Nhiệm vụ đầu tiên của tôi khá đơn giản: kiểm tra và phân tích các file log để tìm hiểu nguyên nhân tại sao hệ thống đang gặp vấn đề hiệu suất. Tôi ngồi trước màn hình, mở terminal và bắt đầu với hàng loạt file log dài bất tận. Tôi nhận được một loạt file log từ các server khác nhau:

/var/log/app1.log
/var/log/app2.log
/var/log/app3.log
...
/var/log/appN.log

Mỗi file chứa hàng ngàn dòng, và tôi không biết bắt đầu từ đâu. Và tôi bắt đầu sử dụng trợ giúp từ google (lúc đó chưa có Chat GPT như bây giờ), thì việc tìm kiếm log lúc đó sẽ diễn ra như thế này:

~ grep "ERROR:::PlaceOrderByUser" /var/log/app1.log

Còn nếu như sử dụng pm2 thì cú pháp sẽ là như thế này

~ grep ./ -rwn -e 'ERROR:::PlaceOrderByUser'

Nhưng ngay lập tức, tôi nhận ra có điều gì đó thực sự không ổn, tôi cảm thấy những dòng log lỗi quá nhiều và nằm rải rác ở khắp mọi nơi, việc tìm kiếm log error từ các file không thể liên kết được. Nếu cần tìm log của một user cụ thể, tôi phải chạy nhiều lệnh grep và kết hợp chúng lại. Hoặc phức tạp hơn nữa thì các function() được gọi trong các anotherFunction() ví dụ:

public boolean orderTicket(ticketId..){
    // 1 - check ticketId is available
    ticketDetail = checkTicket(ticketId)
    // 2 - check ticket store is available
    ticketStore = checkTicketStore(ticketId)

    ...
}

Việc truy vết một request của một User đi qua nhiều function() như vậy là rất khó xác định đồi với một junior như tôi. Công việc này mất hàng giờ đồng hồ chỉ để tìm ra một manh mối nhỏ. Chình vì vậy tôi quyết định là sẽ hỏi ý kiến của Senior.

ELK - Cuộc cách mạng về Distributed Log

Thật vi diệu, sau khi tôi trình bày về những vấn đề mà tôi gặp phải trong quá trình triển khai log thì senior nói:: Không vấn đề gìm, nó thực sự không khó, nó thật sự khó vì bạn chưa triển khai nó bao giờ và quan trọng là làm thế nào để giúp bạn có thể hiểu và triên khai nó nhanh trong dự án của bạn.

Hãy bắt đầu từ những bước chân chập chững, nhận thức đúng sẽ dẫn đền kết quả đúng. Đầu tiên hãy triền khai trên môi trường development về docker cho ba công nghệ được kết hợp đó là ElasticSearch, Logstash, Kibana.

Sau đó tích hợp vào dự án với việc build format log, vì nếu formatter đúng thì khi tìm kiếm sẽ rất nhanh. ...

Sau vài ngày đau khổ triển khai ELK Stack (Elasticsearch, Logstash, và Kibana). Mọi thứ thay đổi ngay lập tức.

Tôi tham gia vào việc cài đặt ELK Stack.

Đây là quá trình setup JAVA 30: Triển khai hệ thống phân tán LOGs ELK cho hệ thống LỚN vetautet.com DDD - Project bạn có thể thực hành tại đó còn ở đây tóm tắt một số thao tác...

Đầu tiên, chúng tôi cài đặt Elasticsearch:

# elasticsearch.yml
network.host: 0.0.0.0
http.port: 9200

Rồi cấu hình Logstash để lấy log từ các file:

# logstash.conf
input {
  file {
    path => "/var/log/*.log"
    start_position => "beginning"
  }
}
filter {
  grok {
    match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{GREEDYDATA:message}" }
  }
}
output {
  elasticsearch {
    hosts => ["http://localhost:9200"]
  }
}

Cuối cùng, chúng tôi sử dụng Kibana để trực quan hóa log:

# kibana.yml
server.host: "0.0.0.0"
elasticsearch.hosts: ["http://localhost:9200"]

Với ELK Stack, mọi log từ các hệ thống được gom về một nơi. Tôi chỉ cần mở Kibana, chọn thời gian và gõ từ khóa:

~ "ERROR:::PlaceOrderByUser" AND level: "ERROR"

Nó rất tuyệt đúng không Junior....

Có thể bạn đã bị missing