Vì vậy, bạn thu thập số liệu. Như chúng ta vậy. Chúng tôi cũng thu thập số liệu. Tất nhiên là cần thiết cho việc kinh doanh. Hôm nay chúng ta sẽ nói về liên kết đầu tiên của hệ thống giám sát của chúng tôi - một máy chủ tổng hợp tương thích với statsd
Từ các bài viết trước của chúng tôi (
Yêu cầu 1. Github, nhà phát triển dự án, đã ngừng hỗ trợ nó: xuất bản các bản vá và bản sửa lỗi, chấp nhận PR của chúng tôi và (không chỉ của chúng tôi). Trong vài tháng qua (khoảng từ tháng 2018 đến tháng 2 năm XNUMX), hoạt động đã tiếp tục trở lại, nhưng trước đó đã có gần XNUMX năm hoàn toàn yên tĩnh. Ngoài ra, dự án đang được phát triển
Yêu cầu 2. Độ chính xác của tính toán. Brubeck thu thập tổng cộng 65536 giá trị để tổng hợp. Trong trường hợp của chúng tôi, đối với một số chỉ số, trong khoảng thời gian tổng hợp (30 giây), nhiều giá trị hơn có thể đến (1 ở mức cao nhất). Kết quả của việc lấy mẫu này, các giá trị tối đa và tối thiểu dường như vô dụng. Ví dụ như thế này:
Như nó đã từng
Lẽ ra nó phải như thế nào
Vì lý do tương tự, số tiền thường được tính toán không chính xác. Thêm vào đây một lỗi tràn float 32-bit, lỗi này thường khiến máy chủ gặp lỗi phân tách khi nhận được một số liệu dường như vô hại và mọi thứ trở nên tuyệt vời. Nhân tiện, lỗi vẫn chưa được sửa.
Và cuối cùng, Yêu cầu X. Tại thời điểm viết bài, chúng tôi sẵn sàng giới thiệu nó cho tất cả 14 triển khai statsd hoạt động ít nhiều mà chúng tôi có thể tìm thấy. Hãy tưởng tượng rằng một số cơ sở hạ tầng đơn lẻ đã phát triển đến mức việc chấp nhận 4 triệu MPS là không còn đủ. Hoặc ngay cả khi nó chưa tăng trưởng, nhưng các số liệu đã quan trọng đối với bạn đến mức ngay cả những sự sụt giảm ngắn hạn, 2-3 phút trên biểu đồ cũng có thể trở nên nghiêm trọng và gây ra những cơn trầm cảm không thể vượt qua ở các nhà quản lý. Vì điều trị trầm cảm là một công việc vô ơn nên cần có các giải pháp kỹ thuật.
Thứ nhất, khả năng chịu lỗi, để một sự cố bất ngờ trên máy chủ không gây ra ngày tận thế zombie tâm thần trong văn phòng. Thứ hai, mở rộng quy mô để có thể chấp nhận hơn 4 triệu MPS mà không cần đào sâu vào ngăn xếp mạng Linux và bình tĩnh phát triển “theo chiều rộng” đến kích thước yêu cầu.
Vì chúng tôi có chỗ để mở rộng quy mô nên chúng tôi quyết định bắt đầu với khả năng chịu lỗi. "VỀ! Khả năng chịu lỗi! Thật đơn giản, chúng tôi có thể làm được,” chúng tôi nghĩ và ra mắt 2 máy chủ, tạo một bản sao brubeck trên mỗi máy chủ. Để làm điều này, chúng tôi phải sao chép lưu lượng truy cập có số liệu vào cả hai máy chủ và thậm chí viết cho việc này
Nếu bạn suy nghĩ một chút về vấn đề và đồng thời đào tuyết bằng xẻng, thì bạn có thể nảy ra ý tưởng rõ ràng sau đây: bạn cần một statsd có thể hoạt động ở chế độ phân tán. Tức là thực hiện đồng bộ hóa giữa các nút về thời gian và số liệu. “Tất nhiên, giải pháp như vậy có thể đã tồn tại,” chúng tôi nói và tìm đến Google…. Và họ không tìm thấy gì cả. Sau khi xem qua tài liệu về các số liệu thống kê khác nhau (
Và sau đó, chúng tôi nhớ về statsd “đồ chơi” - bioyino, được viết tại hackathon Just for Fun (tên của dự án được tạo theo kịch bản trước khi bắt đầu hackathon) và nhận ra rằng chúng tôi rất cần số liệu thống kê của riêng mình. Để làm gì?
- bởi vì có quá ít bản sao statsd trên thế giới,
- bởi vì có thể cung cấp khả năng mở rộng và khả năng mở rộng mong muốn hoặc gần với mức mong muốn (bao gồm đồng bộ hóa các số liệu tổng hợp giữa các máy chủ và giải quyết vấn đề gửi xung đột),
- bởi vì có thể tính toán số liệu chính xác hơn Brubeck,
- bởi vì bạn có thể tự mình thu thập số liệu thống kê chi tiết hơn, điều mà thực tế Brubeck không cung cấp cho chúng tôi,
- bởi vì tôi đã có cơ hội lập trình ứng dụng phòng thí nghiệm quy mô phân tán siêu hiệu suất của riêng mình, ứng dụng này sẽ không lặp lại hoàn toàn kiến trúc của một siêu máy tính tương tự khác... à, thế thôi.
Viết gì lên? Tất nhiên là ở Rust. Tại sao?
- vì đã có giải pháp nguyên mẫu rồi,
- bởi vì tác giả của bài báo đã biết đến Rust vào thời điểm đó và mong muốn viết thứ gì đó trong đó để sản xuất với cơ hội đưa nó vào nguồn mở,
- bởi vì các ngôn ngữ có GC không phù hợp với chúng tôi do tính chất của lưu lượng truy cập nhận được (gần như theo thời gian thực) và việc tạm dừng GC trên thực tế là không thể chấp nhận được,
- bởi vì bạn cần hiệu suất tối đa tương đương với C
- bởi vì Rust cung cấp cho chúng ta khả năng xử lý đồng thời không sợ hãi và nếu chúng ta bắt đầu viết nó bằng C/C++, chúng ta sẽ gặp phải nhiều lỗ hổng hơn, lỗi tràn bộ đệm, điều kiện chạy đua và các từ đáng sợ khác hơn là brubeck.
Cũng có một lập luận chống lại Rust. Công ty không có kinh nghiệm tạo dự án trong Rust và hiện tại chúng tôi cũng không có kế hoạch sử dụng nó trong dự án chính. Vì vậy, có những lo ngại nghiêm trọng rằng sẽ không có kết quả gì, nhưng chúng tôi quyết định nắm lấy cơ hội và cố gắng.
Thời gian trôi qua...
Cuối cùng, sau nhiều lần thất bại, phiên bản hoạt động đầu tiên đã sẵn sàng. Chuyện gì đã xảy ra thế? Đây là những gì đã xảy ra.
Mỗi nút nhận được bộ số liệu riêng và tích lũy chúng, đồng thời không tổng hợp số liệu cho những loại mà cần có bộ đầy đủ của chúng để tổng hợp cuối cùng. Các nút được kết nối với nhau bằng một số loại giao thức khóa phân tán, cho phép bạn chọn trong số chúng một giao thức duy nhất (ở đây chúng tôi đã kêu gọi) xứng đáng để gửi số liệu đến Great One. Vấn đề này hiện đang được giải quyết bởi
Các gói UDP có số liệu không cân bằng giữa các nút trên thiết bị mạng thông qua Round Robin đơn giản. Tất nhiên, phần cứng mạng không phân tích nội dung của các gói và do đó có thể lấy nhiều hơn 4 triệu gói mỗi giây, chưa kể đến các số liệu mà nó không biết gì cả. Nếu chúng tôi tính đến việc các số liệu không xuất hiện lần lượt trong mỗi gói, thì chúng tôi không thấy trước bất kỳ vấn đề về hiệu suất nào ở nơi này. Nếu máy chủ gặp sự cố, thiết bị mạng sẽ nhanh chóng (trong vòng 1-2 giây) phát hiện thực tế này và loại bỏ máy chủ bị lỗi khỏi vòng quay. Do đó, các nút thụ động (tức là không dẫn đầu) có thể được bật và tắt một cách thực tế mà không nhận thấy sự sụt giảm trên biểu đồ. Số tiền tối đa chúng tôi mất là một phần của số liệu xuất hiện ở giây cuối cùng. Việc mất/tắt/chuyển đổi nút dẫn đầu đột ngột vẫn sẽ tạo ra sự bất thường nhỏ (khoảng thời gian 30 giây vẫn không đồng bộ), nhưng nếu có liên lạc giữa các nút, những vấn đề này có thể được giảm thiểu, chẳng hạn như bằng cách gửi các gói đồng bộ hóa .
Một chút về cấu trúc bên trong. Tất nhiên, ứng dụng này là đa luồng, nhưng kiến trúc phân luồng khác với kiến trúc được sử dụng trong brubeck. Các luồng trong brubeck đều giống nhau - mỗi luồng chịu trách nhiệm thu thập và tổng hợp thông tin. Trong bioyino, công nhân được chia thành hai nhóm: những người chịu trách nhiệm về mạng và những người chịu trách nhiệm tổng hợp. Bộ phận này cho phép bạn quản lý ứng dụng linh hoạt hơn tùy thuộc vào loại số liệu: nơi cần tổng hợp chuyên sâu, bạn có thể thêm bộ tổng hợp, nơi có nhiều lưu lượng mạng, bạn có thể thêm số lượng luồng mạng. Hiện tại, trên các máy chủ của chúng tôi, chúng tôi làm việc theo 8 mạng và 4 luồng tổng hợp.
Phần đếm (chịu trách nhiệm tổng hợp) khá nhàm chán. Bộ đệm được lấp đầy bởi các luồng mạng được phân phối giữa các luồng đếm, sau đó chúng được phân tích cú pháp và tổng hợp. Theo yêu cầu, số liệu được cung cấp để gửi đến các nút khác. Tất cả điều này, bao gồm việc gửi dữ liệu giữa các nút và làm việc với Consul, được thực hiện không đồng bộ, chạy trên framework
Nhiều vấn đề hơn trong quá trình phát triển là do phần mạng chịu trách nhiệm nhận số liệu gây ra. Mục tiêu chính của việc tách các luồng mạng thành các thực thể riêng biệt là mong muốn giảm thời gian mà một luồng sử dụng không để đọc dữ liệu từ socket. Các tùy chọn sử dụng UDP không đồng bộ và recvmsg thông thường nhanh chóng biến mất: tùy chọn đầu tiên tiêu tốn quá nhiều CPU không gian người dùng để xử lý sự kiện, tùy chọn thứ hai yêu cầu quá nhiều chuyển đổi ngữ cảnh. Vì vậy hiện nay nó được sử dụng
Ghi
Trong cài đặt mặc định, kích thước bộ đệm được đặt ở mức khá lớn. Nếu bạn đột nhiên quyết định tự mình dùng thử máy chủ, bạn có thể gặp phải thực tế là sau khi gửi một số lượng nhỏ số liệu, chúng sẽ không đến Graphite mà vẫn nằm trong bộ đệm luồng mạng. Để làm việc với một số lượng nhỏ số liệu, bạn cần đặt bufsize và task-queue-size thành các giá trị nhỏ hơn trong config.
Cuối cùng là một số biểu đồ dành cho những người yêu thích biểu đồ.
Thống kê số lượng số liệu đến cho mỗi máy chủ: hơn 2 triệu MPS.
Vô hiệu hóa một trong các nút và phân phối lại các số liệu đến.
Thống kê về số liệu gửi đi: chỉ có một nút luôn gửi - trùm đột kích.
Thống kê hoạt động của từng nút, có tính đến các lỗi trong các mô-đun hệ thống khác nhau.
Chi tiết các số liệu đến (tên số liệu bị ẩn).
Chúng ta dự định làm gì với tất cả những điều này tiếp theo? Tất nhiên là viết mã, chết tiệt...! Dự án ban đầu được lên kế hoạch là nguồn mở và sẽ duy trì như vậy trong suốt vòng đời của nó. Các kế hoạch trước mắt của chúng tôi bao gồm chuyển sang phiên bản Raft của riêng chúng tôi, thay đổi giao thức ngang hàng sang giao thức di động hơn, giới thiệu số liệu thống kê nội bộ bổ sung, các loại số liệu mới, sửa lỗi và các cải tiến khác.
Tất nhiên, mọi người đều được hoan nghênh giúp đỡ trong việc phát triển dự án: tạo PR, Các vấn đề, nếu có thể chúng tôi sẽ phản hồi, cải thiện, v.v.
Như đã nói, đó là tất cả các bạn, hãy mua voi của chúng tôi!
Nguồn: www.habr.com