Bạn có muốn nhận thông báo về nội dung mới không?
Nghiên cứu nhật ký trước tiên
Sau khi tốt nghiệp đại học, tôi đã làm việc ở Amazon. Một trong những bài tập nhập môn đầu tiên của tôi là thiết lập máy chủ web amazon.com và chạy trên máy tính để bàn dành cho nhà phát triển của tôi. Lần đầu tiên tôi thử làm đã thất bại nhưng tôi không chắc mình làm sai ở khâu nào. Một đồng nghiệp tốt bụng đã khuyên rằng tôi nên xem nhật ký để biết được lỗi nằm ở đâu. Anh ấy bảo để làm như vậy, tôi nên dùng lệnh “cat” (mèo). Tôi đã nghĩ là họ đang nói đùa về con mèo hoặc xỏ xiên tôi mà tôi không hiểu. Hồi học đại học, tôi chỉ dùng Linux để biên soạn, sử dụng kiểm soát nguồn và dùng trình soạn thảo văn bản. Vì thế, tôi không biết lệnh “cat” (mèo) thực sự là một lệnh để in một tệp ra định dạng mà tôi có thể cấp dữ liệu vào một chương trình khác nhằm tìm kiếm các mẫu.
Các đồng nghiệp đã chỉ cho tôi những công cụ như cat, grep, sed và awk. Khi được trang bị bộ công cụ mới này, tôi đã nghiền ngẫm nhật ký máy chủ web amazon.com trên máy tính để bàn dành cho nhà phát triển của mình. Ứng dụng máy chủ web đã được đo lường để xuất mọi loại thông tin hữu ích sang nhật ký. Điều này giúp tôi biết mình còn thiếu cấu hình nào khiến máy chủ web không thể khởi động, thiếu cấu hình nào cho biết vị trí có thể gặp lỗi hoặc thiếu cấu hình nào cho biết vị trí không kết nối được với một dịch vụ xuôi tuyến. Trang web này hình thành từ rất nhiều thành phần di động và đó thực sự là một điều bí ẩn đối với tôi khi mới vào nghề. Tuy nhiên, sau khi nghiền ngẫm hệ thống trước tiên, tôi đã biết cách xác định máy chủ hoạt động ra sao và cách tương tác với các thành phần phụ thuộc trong máy chủ mà chỉ cần nhìn vào kết quả của công cụ đo lường.
Lý do cần công cụ đo lường
Yếu tố cần đo lường
Để vận hành dịch vụ theo tiêu chuẩn cao về độ sẵn sàng và độ trễ, chúng tôi, với tư cách là chủ sở hữu dịch vụ, cần đo lường xem hệ thống hoạt động ra sao.
Để đo từ xa khi cần thiết, chủ sở hữu dịch vụ sẽ đo hiệu suất vận hành từ nhiều vị trí để nắm được nhiều phương diện về cách mọi thứ đang vận hành từ đầu đến cuối. Việc này rất phức tạp, ngay cả trong một kiến trúc đơn giản. Đơn cử là một dịch vụ mà khách hàng gọi thông qua cân bằng tải: dịch vụ này sẽ giao tiếp với một bộ nhớ đệm từ xa và cơ sở dữ liệu từ xa. Chúng tôi muốn mỗi thành phần sẽ cho các chỉ số về hành vi của thành phần đó. Chúng tôi cũng muốn có các chỉ số về cách mỗi thành phần nhận biết hành vi của các thành phần khác. Khi chỉ số từ tất cả các phương diện này được tập hợp lại với nhau, chủ sở hữu dịch vụ có thể nhanh chóng truy nguyên nguồn gốc vấn đề và nghiên cứu để tìm nguyên nhân.
Nhiều dịch vụ AWS tự động cung cấp thông tin vận hành chi tiết về tài nguyên của bạn. Ví dụ: Amazon DynamoDB cung cấp cho Amazon CloudWatch các chỉ số về tỷ lệ thành công và tỷ lệ lỗi cũng như độ trễ mà dịch vụ này đo được. Tuy nhiên, khi xây dựng hệ thống sử dụng các dịch vụ này, chúng tôi cần rất nhiều thông tin chi tiết hơn về cách các hệ thống đang hoạt động. Công cụ đo lường cần có mã rõ ràng sẽ ghi lại thời lượng của nhiệm vụ, tần suất thực hiện đường dẫn mã nhất định, siêu dữ liệu về nhiệm vụ đã phân tích và phần nhiệm vụ nào thành công hay thất bại. Nếu một nhóm không bổ sung công cụ đo lường rõ ràng, thì nhóm đó sẽ buộc phải vận hành dịch vụ của mình dưới dạng một hộp đen.
Ví dụ: nếu chúng tôi triển khai một hoạt động API dịch vụ sẽ truy xuất thông tin sản phẩm theo ID sản phẩm, thì mã có thể trông giống như ví dụ sau đây. Mã này sẽ tra cứu thông tin sản phẩm trong một bộ nhớ đệm cục bộ, sau đó là bộ nhớ đệm từ xa rồi đến cơ sở dữ liệu:
public GetProductInfoResponse getProductInfo(GetProductInfoRequest request) {
// check our local cache
ProductInfo info = localCache.get(request.getProductId());
// check the remote cache if we didn't find it in the local cache
if (info == null) {
info = remoteCache.get(request.getProductId());
localCache.put(info);
}
// finally check the database if we didn't have it in either cache
if (info == null) {
info = db.query(request.getProductId());
localCache.put(info);
remoteCache.put(info);
}
return info;
}
Nếu vận hành dịch vụ này, thì tôi sẽ cần rất nhiều công cụ đo lường trong mã này để có thể hiểu hành vi của dịch vụ trong môi trường sản xuất. Tôi sẽ cần khả năng khắc phục những yêu cầu bị chậm hoặc lỗi và theo dõi xu hướng cũng như dấu hiệu mà các thành phần phụ thuộc khác nhau có quy mô thấp hơn hoặc có hành vi ngoài dự kiến. Đây là mã đó, kèm theo ghi chú một số câu hỏi mà tôi cần giải đáp được về hệ thống sản xuất nói chung hoặc cho một yêu cầu cụ thể:
public GetProductInfoResponse getProductInfo(GetProductInfoRequest request) {
// Which product are we looking up?
// Who called the API? What product category is this in?
// Did we find the item in the local cache?
ProductInfo info = localCache.get(request.getProductId());
if (info == null) {
// Was the item in the remote cache?
// How long did it take to read from the remote cache?
// How long did it take to deserialize the object from the cache?
info = remoteCache.get(request.getProductId());
// How full is the local cache?
localCache.put(info);
}
// finally check the database if we didn't have it in either cache
if (info == null) {
// How long did the database query take?
// Did the query succeed?
// If it failed, is it because it timed out? Or was it an invalid query? Did we lose our database connection?
// If it timed out, was our connection pool full? Did we fail to connect to the database? Or was it just slow to respond?
info = db.query(request.getProductId());
// How long did populating the caches take?
// Were they full and did they evict other items?
localCache.put(info);
remoteCache.put(info);
}
// How big was this product info object?
return info;
}
Mã để trả lời toàn bộ các câu hỏi đó (và nhiều hơn thế) dài hơn lô-gic công việc thực tế một chút. Một số thư viện có thể giúp giảm số lượng mã công cụ đo lường, tuy nhiên, nhà phát triển vẫn phải đặt các câu hỏi về thông tin chi tiết mà các thư viện này sẽ cần rồi tập trung vào việc kết nối công cụ đo lường.
Khi khắc phục một yêu cầu di chuyển qua hệ thống phân tán, có lẽ bạn khó có thể hiểu được điều gì xảy ra nếu chỉ nhìn vào yêu cầu đó dựa trên một tương tác. Để xâu chuỗi các sự kiện, chúng tôi thấy việc tập hợp mọi phép đo về tất cả các hệ thống này về cùng một nơi là cách làm khá hữu ích. Trước khi chúng tôi có thể làm điều đó, mỗi dịch vụ phải được đo lường để ghi lại ID theo dõi cho mỗi nhiệm vụ và để cung cấp ID theo dõi đó cho mỗi dịch vụ khác cũng cộng tác trên nhiệm vụ đó. Chúng tôi có thể thu thập công cụ đo lường trên các hệ thống cho một ID theo dõi cụ thể sau một dữ kiện theo yêu cầu hoặc trong thời gian gần thực bằng một dịch vụ như AWS X-Ray.
Phân tích toàn diện
Công cụ đo lường cho phép khắc phục sự cố ở nhiều cấp độ, từ cái nhìn sơ lược về các chỉ số để xem có vấn đề bất thường nào quá khó phát hiện để kích hoạt báo động hay không, để tiến hành điều tra nhằm tìm hiểu nguyên nhân của những vấn đề bất thường đó.
Ở cấp độ cao nhất, công cụ đo lường được tích hợp vào các chỉ số có thể kích hoạt báo động và hiển thị trên bảng thông tin. Những chỉ số tích hợp này cho phép người vận hành theo dõi tốc độ yêu cầu tổng thể, độ trễ của các lệnh gọi dịch vụ và tỷ lệ lỗi. Những báo động và chỉ số này giúp chúng tôi nhận biết vấn đề bất thường hay các thay đổi cần điều tra.
Sau khi phát hiện một vấn đề bất thường, chúng tôi cần tìm hiểu vì sao vấn đề đó lại xảy ra. Để trả lời câu hỏi đó, chúng tôi còn có thể dựa vào các chỉ số mà công cụ đo lường khác cung cấp. Khi đo lường thời gian cần để thực hiện các phần khác nhau trong khi phân phối một yêu cầu, chúng tôi có thể biết phần nào trong quy trình đang chậm hơn bình thường hoặc thường xuyên kích hoạt lỗi hơn.
Mặc dù các bộ hẹn giờ và chỉ số tích hợp có thể giúp chúng tôi tìm ra nguyên nhân hoặc đánh dấu một khu vực cần điều tra, nhưng không phải lúc nào chúng cũng cung cấp một giải thích đầy đủ. Ví dụ: khi nhìn vào các chỉ số, chúng tôi có thể thấy rằng lỗi đến từ một hoạt động của API cụ thể nhưng các chỉ số không thể cung cấp thông tin ở mức cụ thể về lý do hoạt động đó gặp lỗi. Lúc này, chúng tôi sẽ nhìn vào dữ liệu nhật ký chi tiết, chưa xử lý theo dịch vụ trong khoảng thời gian đó. Sau đó, nhật ký chưa xử lý sẽ cho biết nguồn gốc vấn đề, lỗi cụ thể đã xảy ra hay khía cạnh cụ thể của yêu cầu đã kích hoạt một số trường hợp khó và bất khả thi.
Cách chúng tôi đo lường
Công cụ đo lường yêu cầu phải viết mã. Điều đó có nghĩa là khi triển khai chức năng mới, chúng tôi cần dành thời gian để bổ sung mã phụ nhằm cho biết điều gì đã xảy ra, thành công hay lỗi và thời lượng xảy ra. Vì công cụ đo lường chỉ là một nhiệm vụ viết mã thông thường, nên dần dần, Amazon đã hình thành những phương pháp xử lý các mẫu thường gặp: chuẩn hóa cho thư viện công cụ đo lường phổ biến và chuẩn hóa cho báo cáo chỉ số dựa trên nhật ký có cấu trúc.
Chuẩn hóa thư viện công cụ đo lường chỉ số giúp chủ thư viện cung cấp cho người dùng thư viện thông tin chi tiết về cách thư viện vận hành. Ví dụ: các máy khách HTTP thường dùng sẽ tích hợp với các thư viện phổ biến này để nếu một nhóm dịch vụ triển khai lệnh gọi từ xa tới một dịch vụ khác, thì các máy khách sẽ tự động nhận được công cụ đo lường về những lệnh gọi đó.
Khi một ứng dụng có công cụ đo lường chạy và thực hiện công việc, dữ liệu đo lường từ xa được ghi vào một tệp nhật ký có cấu trúc. Nói chung, dữ liệu được cung cấp dưới dạng một mục nhật ký trên mỗi “đơn vị công việc”, cho dù đó là yêu cầu tới dịch vụ HTTP hay thông báo được lấy từ hàng đợi.
Ở Amazon, các phép đo trong ứng dụng không được tích hợp và đôi khi bị đẩy vào một hệ thống tích hợp chỉ số. Tất cả các bộ hẹn giờ và bộ đếm cho mọi phần công việc đều được ghi vào tệp nhật ký. Từ đó, các nhật ký được xử lý và số liệu tích hợp được tính toán sau một dữ kiện của một số hệ thống khác. Bằng cách này, chúng tôi có được mọi thông tin từ chỉ số vận hành tích hợp cấp cao cho đến dữ liệu khắc phục sự cố chi tiết ở cấp độ yêu cầu, tất cả chỉ nhờ vào phương pháp viết mã đo lường. Ở Amazon, chúng tôi ghi nhật ký trước rồi mới tạo chỉ số tích hợp.
Đo lường thông qua ghi nhật ký
Chúng tôi thường đo lường các dịch vụ của mình để tạo hai loại dữ liệu nhật ký: dữ liệu yêu cầu và dữ liệu gỡ lỗi. Dữ liệu nhật ký yêu cầu thường được trình bày dưới dạng mục nhật ký có cấu trúc cho mỗi đơn vị công việc. Dữ liệu này chứa các thuộc tính về yêu cầu và người yêu cầu, nội dung yêu cầu, bộ đếm tần suất yêu cầu và bộ hẹn giờ thời lượng diễn ra. Nhật ký yêu cầu phân phối dưới dạng một nhật ký kiểm tra và một nguồn theo dõi cho mọi hoạt động xảy ra trong dịch vụ. Dữ liệu gỡ lỗi bao gồm dữ liệu có cấu trúc rời rạc hoặc phi cấu trúc về những dòng gỡ lỗi mà ứng dụng cung cấp. Thông thường, đó là các mục nhật ký phi cấu trúc như lỗi Log4j hoặc dòng nhật ký cảnh báo. Ở Amazon, hai loại dữ liệu này thường được ghi vào các tệp nhật ký riêng, một phần vì những lý do trước đây, nhưng cũng bởi nó có thể giúp việc phân tích nhật ký trở nên tiện lợi hơn trên một định dạng mục nhật ký đồng nhất.
Các tác nhân như CloudWatch Logs Agent xử lý cả hai loại dữ liệu nhật ký trong thời gian thực và gửi nhật ký vào CloudWatch Logs. Đổi lại, CloudWatch Logs tạo ra chỉ số tích hợp về dịch vụ trong thời gian gần thực. Amazon CloudWatch Alarms sẽ đọc các chỉ số tích hợp và kích hoạt báo động.
Mặc dù việc ghi nhật ký quá chi tiết về từng yêu cầu có thể gây tốn kém, nhưng ở Amazon, chúng tôi thấy việc này cực kỳ quan trọng. Sau cùng, chúng tôi cần điều tra về sự cố tạm thời với độ sẵn sàng, độ trễ tăng vọt và vấn đề mà khách hàng báo cáo. Nếu không có nhật ký chi tiết, chúng tôi không thể trả lời khách hàng và cải thiện dịch vụ của họ.
Kiểm soát các chi tiết
Chủ đề về hoạt động giám sát và báo động rất rộng. Trong bài viết này, chúng tôi không đề cập đến các chủ đề như thiết lập và tinh chỉnh ngưỡng báo động, sắp xếp các bảng thông tin vận hành, đo lường hiệu suất từ cả phía máy chủ lẫn máy khách, liên tục chạy các ứng dụng “canary” và chọn hệ thống phù hợp dùng để tích hợp các chỉ số và phân tích nhật ký.
Bài viết này tập trung vào nhu cầu đo lường các ứng dụng của chúng tôi để tạo ra dữ liệu đo lường chưa xử lý phù hợp. Chúng tôi sẽ mô tả những điều mà các nhóm ở Amazon nỗ lực đưa vào (hoặc tránh) khi đo lường các ứng dụng của họ.
Cách ghi nhật ký yêu cầu hay nhất
Trong phần này, tôi sẽ mô tả những thói quen tốt mà chúng tôi đã lĩnh hội được về việc ghi nhật ký dữ liệu “theo đơn vị công việc” có cấu trúc khi làm việc ở Amazon. Một nhật ký đáp ứng những tiêu chí này sẽ chứa các bộ đếm cho biết tần suất các hoạt động diễn ra, bộ hẹn giờ chứa thời lượng hoạt động diễn ra và các thuộc tính bao gồm siêu dữ liệu về từng đơn vị công việc.
• Phát hành một mục nhật ký yêu cầu cho mỗi đơn vị công việc. Một đơn vị công việc thường là một yêu cầu mà dịch vụ của chúng tôi nhận được hoặc là một thông báo lấy từ một hàng đợi. Chúng tôi ghi một mục nhật ký dịch vụ cho mỗi yêu cầu mà dịch vụ của mình nhận được. Chúng tôi không kết hợp nhiều đơn vị công việc cùng nhau. Bằng cách này, khi khắc phục một yêu cầu bị lỗi, chúng tôi chỉ cần nhìn vào một mục nhật ký. Mục nhật ký này chứa các tham số đầu vào liên quan về yêu cầu để xem mục đích của yêu cầu này, thông tin về người gọi và toàn bộ thông tin hẹn giờ cũng như bộ đếm ở cùng một nơi.
• Chỉ phát hành một mục nhật ký yêu cầu cho một yêu cầu bất kỳ. Trong khi triển khai dịch vụ không theo khối, việc phát hành từng mục nhật ký riêng cho mỗi giai đoạn trong một quy trình xử lý dường như có vẻ tiện lợi. Thế nhưng, chúng tôi khắc phục sự cố những hệ thống này thành công hơn bằng cách cố gắng khám phá một “đối tượng chỉ số” duy nhất giữa các giai đoạn trong quy trình, sau đó xếp các chỉ số theo thứ tự như một đơn vị sau khi hoàn thành toàn bộ các giai đoạn. Nếu mỗi đơn vị công việc có nhiều mục nhật ký thì sẽ khó phân tích hơn, đồng thời làm tăng chi phí ghi nhật ký vốn đã tốn kém theo cấp số nhân. Nếu ghi một dịch vụ không theo khối mới, chúng tôi cố gắng lên kế hoạch trước cho vòng đời ghi nhật ký chỉ số vì về sau, rất khó để sắp xếp lại và chỉnh sửa hoạt động này.
• Chia các nhiệm vụ chạy mất nhiều thời gian thành nhiều mục nhật ký. Trái với đề xuất nêu trên, nếu có một nhiệm vụ chạy mất nhiều thời gian, nhiều phút hoặc nhiều giờ giống như một quy trình, thì chúng tôi có thể quyết định định kỳ phát hành một mục nhật ký riêng để có thể xác định xem nhiệm vụ có tiến triển hay không hoặc nhiệm vụ bị chậm trễ ở vị trí nào.
• Ghi lại các chi tiết về yêu cầu trước khi thực hiện các hoạt động như xác thực. Một điều quan trọng là hoạt động khắc phục sự cố và ghi nhật ký kiểm tra cần phải ghi đủ thông tin về yêu cầu để chúng tôi biết được yêu cầu đó đang cố đạt được điều gì. Chúng tôi thấy việc ghi nhật ký thông tin này càng sớm càng tốt trước khi logic xác thực, xác nhận hoặc điều chỉnh có cơ hội từ chối yêu cầu là điều cũng vô cùng quan trọng. Nếu ghi nhật ký thông tin từ một yêu cầu đến, thì chúng tôi đảm bảo sẽ thanh lọc thông tin đầu vào (mã hóa, thoát và lược bớt) trước khi ghi. Ví dụ: chúng tôi không muốn bao gồm các chuỗi dài 1 MB trong mục nhật ký dịch vụ nếu người gọi đã chuyển một chuỗi như vậy. Làm như thế sẽ khiến ổ đĩa nhanh đầy và chúng tôi tốn nhiều chi phí lưu trữ nhật ký hơn dự kiến. Một ví dụ thanh lọc khác là lọc các ký tự kiểm soát ASCII hoặc thoát khỏi các chuỗi liên quan đến định dạng nhật ký. Nếu người gọi chuyển một mục nhật ký dịch vụ của chính họ và họ có thể đưa mục nhật ký đó vào nhật ký của chúng tôi thì điều này có thể gây ra sự nhầm lẫn! Vui lòng xem cả: https://xkcd.com/327/
• Chuẩn bị cách ghi nhật ký ngày càng dài. Khi khắc phục một số loại sự cố, nhật ký sẽ không có đủ chi tiết về yêu cầu gặp vấn đề để tìm hiểu lý do chúng bị lỗi. Thông tin đó có thể nằm trong dịch vụ, nhưng lượng thông tin này có thể quá lớn để lúc nào cũng ghi được nhật ký. Việc sử dụng một nút cấu hình có thể xoay để tăng tạm thời độ dài của nhật ký trong khi điều tra sự cố có thể giúp ích cho bạn. Bạn có thể xoay nút này trên từng máy chủ hoặc từng máy khách hoặc ở tốc độ lấy mẫu trên toàn bộ nhóm thiết bị. Bạn cần nhớ xoay lại nút này khi đã hoàn tất.
• Đặt tên ngắn cho chỉ số (nhưng không quá ngắn). Amazon đã sử dụng một cách lập chuỗi nhật ký dịch vụ trong hơn 15 năm qua. Trong cách lập chuỗi này, tên của mỗi bộ đếm và bộ hẹn giờ được lặp lại ở định dạng văn bản thuần túy trong mọi mục nhật ký dịch vụ. Để giúp giảm thiểu chi phí ghi nhật ký, chúng tôi sử dụng tên bộ hẹn giờ ngắn và có tính mô tả. Amazon bắt đầu áp dụng định dạng lập chuỗi mới dựa trên giao thức lập chuỗi nhị phân được gọi là Amazon Ion. Cuối cùng, bạn cần chọn một định dạng mà công cụ phân tích nhật ký có thể hiểu trong khi vẫn có thể lập chuỗi, hủy chuỗi và lưu trữ hiệu quả nhất có thể.
• Đảm bảo bộ nhớ nhật ký đủ lớn để ghi nhật ký ở công suất tối đa. Chúng tôi kiểm thử tải dịch vụ ở mức tải duy trì tối đa (hoặc thậm chí quá tải) trong nhiều giờ. Chúng tôi cần đảm bảo rằng khi dịch vụ của mình gặp tình trạng lưu lượng quá mức, thì dịch vụ vẫn có tài nguyên để xuất nhật ký tương đương với tốc độ tạo mục nhật ký mới, nếu không, ổ đĩa sẽ bị đầy. Bạn cũng có thể đặt cấu hình nhiệm vụ ghi nhật ký diễn ra trên một phân vùng hệ thống tệp khác chứ không phải phân vùng gốc để hệ thống không bị lỗi khi phải ghi nhật ký quá mức. Chúng tôi sẽ thảo luận về biện pháp khắc phục khác cho vấn đề này sau, như sử dụng cách lấy mẫu động tỷ lệ với công suất, nhưng dù chiến lược là gì thì quan trọng nhất vẫn là kiểm thử.
• Cân nhắc hành vi hệ thống khi ổ đĩa đầy. Khi một ổ đĩa của máy chủ đã đầy, thì ổ đĩa đó không thể ghi nhật ký nữa. Khi điều đó xảy ra, dịch vụ nên dừng tiếp nhận yêu cầu hay bỏ nhật ký và tiếp tục vận hành mà không giám sát? Vận hành mà không ghi nhật ký tiềm ẩn nhiều rủi ro. Do đó, chúng tôi kiểm thử hệ thống để đảm bảo phát hiện ra những máy chủ có ổ đĩa gần đầy.
• Đồng bộ hóa đồng hồ. Khái niệm “thời gian” trong hệ thống phân tán là một khái niệm phức tạp. Chúng tôi không dựa vào đồng bộ hóa đồng hồ trong thuật toán phân tán nhưng đồng hồ lại cần thiết để nhật ký có giá trị. Chúng tôi chạy các daemon như Chrony hoặc ntpd để đồng bộ hóa đồng hồ và chúng tôi theo dõi máy chủ để biết tỷ lệ trôi nhịp đồng hồ. Để làm điều này dễ dàng hơn, hãy tham khảo Dịch vụ đồng bộ hóa thời gian Amazon.
• Phát hành chỉ số sẵn sàng bằng không. Việc đếm lỗi rất hữu ích, nhưng tỷ lệ phần trăm lỗi cũng có thể hữu ích như vậy. Để đo lường chỉ số “tỷ lệ phần trăm sẵn sàng”, chúng tôi có một chiến lược hữu ích đó là dùng số 1 khi yêu cầu thành công và số 0 khi yêu cầu bị lỗi. Sau đó, số liệu thống kê “trung bình” của chỉ số nhận được chính là tỷ lệ sẵn sàng. Việc chủ định sử dụng điểm dữ liệu 0 cũng có thể hữu ích ở các tình huống khác. Ví dụ: nếu một ứng dụng tiến hành bầu chọn đường chỉ dẫn, thì việc định kỳ phát hành số 1 khi một quy trình là đường chỉ dẫn và số 0 khi quy trình không phải là đường chỉ dẫn có thể hữu ích trong việc theo dõi tình trạng của những đường theo sau. Bằng cách này, nếu một quy trình dừng cho kết quả là 0, thì bạn có thể dễ dàng biết rằng đã xảy ra lỗi nào đó và không thể kiểm soát nếu điều gì đó xảy ra với đường chỉ dẫn.
• Ghi nhật ký độ sẵn sàng và độ trễ của toàn bộ các thành phần phụ thuộc. Chúng tôi thấy điều này đặc biệt hữu ích khi trả lời câu hỏi “vì sao yêu cầu bị chậm?” hay “vì sao yêu cầu không thành công?” Khi không có nhật ký này, chúng tôi chỉ có thể so sánh các biểu đồ của thành phần phụ thuộc với các biểu đồ của một dịch vụ, và đoán xem liệu một sự tăng vọt trong độ trễ của một dịch vụ phụ thuộc có khiến yêu cầu mà chúng tôi đang điều tra gặp lỗi hay không. Nhiều framework dịch vụ và máy khách tự động khám phá các chỉ số nhưng các framework khác (như SDK AWS chẳng hạn) lại yêu cầu đo lường thủ công.
• Phân chi chỉ số phụ thuộc theo lệnh gọi, tài nguyên, mã trạng thái, v.v. Nếu tương tác với cùng một thành phần phụ thuộc nhiều lần trong cùng một đơn vị công việc, thì chúng tôi bao gồm các chỉ số về từng lệnh gọi riêng biệt và giúp làm rõ tài nguyên nào đã tương tác với mỗi yêu cầu. Ví dụ: khi gọi Amazon DynamoDB, một số nhóm thấy hữu ích khi bao gồm chỉ số thời gian và độ trễ theo bảng, mã lỗi và thậm chí là số lần thử lại. Điều này giúp dễ dàng khắc phục các trường hợp mà dịch vụ bị chậm khi thử lại do gặp lỗi kiểm tra điều kiện. Các chỉ số này cũng hé lộ những trường hợp tăng độ trễ do máy khách do điều chỉnh số lần thử lại hoặc phân trang trong một bộ kết quả chứ không phải do độ trễ mạng hay mất gói.
• Ghi lại chiều sâu hàng đợi bộ nhớ khi truy cập. Nếu một yêu cầu tương tác với một hàng đợi và chúng tôi đang lấy một đối tượng ra khỏi hàng đợi đó hoặc đặt đối tượng nào đó vào hàng đợi, thì chúng tôi ghi lại chiều sâu hàng đợi hiện tại vào đối tượng chỉ số khi ở trong hàng đợi đó. Đối với hàng đợi trong bộ nhớ, việc lấy thông tin này không hề tốn kém. Đối với hàng đợi phân tán, siêu dữ liệu này có thể được cung cấp miễn phí trong các phản hồi lệnh gọi API. Việc ghi nhật ký này sẽ giúp tìm phần tồn đọng và nguồn gây trễ trong tương lai. Ngoài ra, khi lấy một đối tượng ra khỏi hàng đợi, chúng tôi sẽ đo khoảng thời gian đối tượng đó đã ở trong hàng đợi. Điều này có nghĩa là chúng tôi cần thêm chỉ số “thời gian trong hàng đợi” của chính mình vào thông báo trước khi xếp chỉ số đó vào vị trí đầu tiên trong hàng đợi.
• Thêm một bộ đếm bổ sung cho mỗi lý do lỗi. Hãy cân nhắc việc thêm mã sẽ đếm lý do lỗi cụ thể cho mọi yêu cầu không thành công. Nhật ký ứng dụng sẽ bao gồm thông tin dẫn đến lỗi và thông báo ngoại lệ chi tiết. Tuy nhiên, chúng tôi cũng thấy hữu ích khi biết được xu hướng lý do lỗi trong chỉ số này theo thời gian mà không phải tìm thông tin đó trong nhật ký ứng dụng. Thật tiện lợi khi bắt đầu với một chỉ số riêng cho từng nhóm ngoại lệ lỗi.
• Sắp xếp lỗi theo danh mục nguyên nhân. Nếu toàn bộ lỗi được gộp vào cùng một chỉ số, thì chỉ số đó sẽ rất lộn xộn và không có ích. Tối thiểu, chúng tôi thấy cần phải tách “lỗi của máy khách” khỏi “lỗi của máy chủ”. Ngoài ra, việc phân chia nhỏ hơn có thể hữu ích. Ví dụ: trong DynamoDB, máy khách có thể tạo các yêu cầu ghi có điều kiện trả về một lỗi nếu mục mà chúng đang sửa đổi không khớp với điều kiện đặt trước trong yêu cầu. Đây là những lỗi chủ ý và thỉnh thoảng xảy ra. Trong khi đó, lỗi “yêu cầu không hợp lệ” từ máy khách có nhiều khả năng là lỗi mà chúng tôi cần khắc phục.
• Ghi siêu dữ liệu quan trọng về đơn vị công việc. Trong một nhật ký chỉ số có cấu trúc, chúng tôi cũng bao gồm đủ siêu dữ liệu về yêu cầu để sau này có thể xác định người yêu cầu và mục đích yêu cầu. Điều này bao gồm siêu dữ liệu mà một khách hàng sẽ muốn chúng tôi có trong nhật ký khi họ liên hệ để giải quyết vấn đề. Ví dụ: DynamoDB ghi tên của bảng mà yêu cầu tương tác cũng như siêu dữ liệu như liệu hoạt động đọc có phải là một hoạt động đọc thống nhất hay không. Tuy nhiên, DynamoDB lại không ghi dữ liệu được lưu trữ vào hoặc truy xuất từ cơ sở dữ liệu.
• Bảo vệ nhật ký bằng cách mã hóa và kiểm soát quyền truy cập. Vì nhật ký có thể chứa thông tin nhạy cảm ở mức độ nào đó, nên chúng tôi thực hiện các biện pháp bảo vệ và bảo mật dữ liệu đó. Các biện pháp này bao gồm mã hóa nhật ký, chỉ cho phép người vận hành khắc phục sự cố truy cập và định kỳ đặt cơ sở cho quyền truy cập đó.
• Tránh đưa những thông tin quá nhạy cảm vào nhật ký. Nhật ký cần chứa một số thông tin nhạy cảm để phát huy hiệu quả. Ở Amazon, chúng tôi thấy việc nhật ký chứa đủ thông tin để biết người đưa ra yêu cầu khá quan trọng. Tuy nhiên, chúng tôi loại bỏ thông tin quá nhạy cảm như những thông số trong yêu cầu không ảnh hưởng đến cách định tuyến hoặc hành vi xử lý yêu cầu. Ví dụ: nếu mã đang phân tích cú pháp thông điệp của khách hàng và không phân tích được, thì bạn không nên ghi nhật ký phần tải dữ liệu để bảo vệ quyền riêng tư của khách hàng, cũng như những thông tin có thể khiến khó khắc phục sự cố sau này. Chúng tôi sử dụng công cụ để đưa ra quyết định về dữ liệu có thể ghi nhật ký theo cách cho phép thay vì không cho phép để tránh ghi nhật ký thông số nhạy cảm mới được thêm về sau. Các dịch vụ như Amazon API Gateway cho phép đặt cấu hình những dữ liệu được đưa vào nhật ký truy cập, đóng vai trò là một cơ chế cho phép hiệu quả.
• Ghi nhật ký ID theo dõi và cung cấp lệnh gọi phụ trợ. Một yêu cầu nào đó của khách hàng sẽ có khả năng liên quan đến nhiều dịch vụ cộng tác với nhau. Có thể đó chỉ là hai hay ba dịch vụ đối với nhiều yêu cầu AWS, nhưng cũng có thể là nhiều dịch vụ đối với các yêu cầu của amazon.com. Để biết được điều gì xảy ra khi khắc phục sự cố cho một hệ thống phân tán, chúng tôi cung cấp cùng một ID theo dõi giữa các hệ thống này để có thể tập hợp nhật ký từ nhiều hệ thống khác nhau để xem lỗi xảy ra ở đâu. ID theo dõi là một loại ID yêu cầu meta được in trên một đơn vị công việc phân tán bằng dịch vụ “cửa trước”, đó chính là điểm bắt đầu cho đơn vị công việc. AWS X-Ray là một dịch vụ hữu ích khi cung cấp một số cách điền thông tin này. Chúng tôi thấy việc chuyển nguồn theo dõi tới thành phần phụ thuộc rất quan trọng. Trong môi trường đa luồng, framework rất khó cung cấp thông tin này thay cho chúng tôi (và còn dễ gặp lỗi). Do đó, chúng tôi đã hình thành thói quen chuyển ID theo dõi và nội dung yêu cầu khác (như đối tượng chỉ số!) trong chữ ký phương thức của mình. Chúng tôi cũng thấy thật tiện lợi khi chuyển một đối tượng Ngữ cảnh trong chữ ký phương thức để không phải sắp xếp lại khi tìm mẫu tương tự để chuyển trong tương lai. Đối với các nhóm AWS, đó không chỉ là khắc phục sự cố hệ thống của chúng tôi mà còn là việc khách hàng khắc phục sự cố của chính họ. Khách hàng tin tưởng vào nguồn theo dõi AWS X-Ray được chuyển giữa các dịch vụ AWS khi chúng tương tác với nhau thay mặt khách hàng. Điều đó yêu cầu chúng tôi cung cấp ID theo dõi AWS X-Ray của khách hàng giữa các dịch vụ để họ có thể nhận được dữ liệu theo dõi đầy đủ.
• Ghi nhật ký các chỉ số độ trễ khác nhau phụ thuộc vào kích thước và mã trạng thái. Lỗi thường xảy ra rất nhanh, như phản hồi lỗi xác thực, điều chỉnh và từ chối quyền truy cập. Nếu các máy khách bắt đầu bị điều chỉnh ở tốc độ cao, thì độ trễ trông có vẻ ổn (nhưng thực ra không phải như vậy). Để tránh làm loãng chỉ số này, chúng tôi ghi bộ hẹn giờ riêng cho mỗi phản hồi thành công, đồng thời tập trung vào chỉ số đó trên bảng thông tin và báo động thay vì sử dụng một chỉ số Thời gian chung. Tương tự như vậy, nếu có một hoạt động có thể bị chậm hơn phụ thuộc vào kích thước đầu vào hoặc kích thước phản hồi, thì chúng tôi cân nhắc việc phát hành một chỉ số độ trễ theo phân loại, như SmallRequestLatency và LargeRequestLatency. Ngoài ra, chúng tôi đảm bảo yêu cầu và phản hồi của mình được ràng buộc phù hợp để tránh chế độ lỗi và sự sụt giảm phức tạp, nhưng ngay cả trong dịch vụ được thiết kế kỹ lưỡng thì kỹ thuật tạo bộ chứa chỉ số này cũng có thể cô lập hành vi của khách hàng và loại bỏ yếu tố rườm rà khỏi bảng thông tin.
Cách làm hay nhất đối với nhật ký ứng dụng
Phần này mô tả thói quen tốt mà chúng tôi đã lĩnh hội được ở Amazon khi ghi dữ liệu nhật ký gỡ lỗi phi cấu trúc.
• Loại bỏ spam khỏi nhật ký ứng dụng. Mặc dù chúng tôi có thể có các tuyên bố nhật ký cấp độ THÔNG TIN và GỠ LỖI trên đường dẫn yêu cầu để hỗ trợ hoạt động phát triển và gỡ lỗi trong môi trường kiểm thử, nhưng chúng tôi cân nhắc việc tắt những cấp độ nhật ký này trong môi trường sản xuất. Thay vì dựa vào nhật ký ứng dụng để biết thông tin theo dõi yêu cầu, chúng tôi coi nhật ký dịch vụ là một ví trí lưu trữ thông tin theo dõi có thể dễ dàng tạo ra các chỉ số và xem xu hướng tích hợp theo thời gian. Tuy nhiên, không có quy tắc đúng - sai nào ở đây cả. Phương pháp của chúng tôi là liên tục xem xét nhật ký để xem chúng có quá nhiễu không (hay chưa đủ nhiễu) và điều chỉnh cấp độ nhật ký theo thời gian. Ví dụ: khi nghiên cứu nhật ký, chúng tôi thường thấy các tuyên bố nhật ký quá nhiễu hay các chỉ số chúng tôi mong muốn có được quá nhiễu. Thật may là những cải tiến này thường dễ dàng tiến hành nên chúng tôi đã tạo thói quen lập hồ sơ theo dõi nhanh các mục tồn đọng để nhật ký luôn rõ ràng.
• Bao gồm ID yêu cầu tương ứng. Khi khắc phục lỗi trong nhật ký ứng dụng, chúng tôi thường muốn xem các chi tiết về yêu cầu hoặc lệnh gọi kích hoạt lỗi đó. Nếu cả hai nhật ký đều chứa cùng một ID yêu cầu, thì chúng tôi có thể dễ dàng chuyển đổi giữa hai nhật ký. Thư viện ghi nhật ký ứng dụng sẽ ghi ID yêu cầu tương ứng nếu được cấu hình đúng cách và ID yêu cầu được đặt là ThreadLocal. Nếu một ứng dụng có nhiều luồng, hãy đặc biệt thận trọng với việc đặt ID yêu cầu chính xác khi một luồng bắt đầu làm việc trên một yêu cầu mới.
• Giới hạn tốc độ spam lỗi trong nhật ký ứng dụng. Thông thường, một dịch vụ sẽ không phát hành nhiều nhật ký ứng dụng, nhưng nếu dịch vụ đó bắt đầu cho thấy một lượng lỗi lớn, thì dịch vụ có thể đột ngột bắt đầu ghi mục nhật ký rất lớn ở tốc độ cao với các dò ngăn xếp. Chúng tôi có một cách để ngăn chặn việc này là giới hạn tốc độ tần suất ghi nhật ký của một bộ ghi nhật ký nhất định.
• Ưu tiên chuỗi định dạng hơn String#format hoặc ghép chuỗi. Hoạt động của API nhật ký ứng dụng cũ chấp nhận một thông báo chuỗi thay vì api chuỗi định dạng varargs của log4j2. Nếu mã được đo lường bằng tuyên bố GỠ LỖI nhưng phiên bản sản xuất lại được đặt cấu hình ở cấp độ LỖI, thì việc định dạng chuỗi thông báo GỠ LỖI bị bỏ qua có thể là một hoạt động vô ích. Một số hoạt động của API ghi nhật ký hỗ trợ chuyển các đối tượng tùy ý sẽ chỉ gọi phương pháp toString() khi mục nhật ký được ghi.
• Ghi ID yêu cầu từ lệnh gọi dịch vụ bị lỗi. Nếu một dịch vụ được gọi và trả về lỗi, thì dịch vụ đó có khả năng trả về ID yêu cầu. Chúng tôi thấy hữu ích khi bao gồm ID yêu cầu vào nhật ký để nếu cần theo dõi với chủ sở hữu dịch vụ đó, thì chúng tôi có cách để giúp họ dễ dàng tìm thấy mục nhật ký dịch vụ tương ứng của chính họ. Lỗi hết thời gian chờ khiến việc này khá khó vì dịch vụ có thể chưa trả về ID yêu cầu hoặc thư viện máy khách có thể không phân tích cú pháp ID này. Tuy nhiên, nếu nhận được ID yêu cầu từ dịch vụ, thì chúng tôi sẽ ghi lại.
Cách làm hay nhất với dịch vụ có thông lượng cao
Đối với hầu hết các dịch vụ chính ở Amazon, việc ghi mọi yêu cầu không tạo ra chi phí quản lý bất hợp lý. Dịch vụ có thông lượng cao hơn sẽ đi vào vùng xám hơn nhưng chúng tôi thường vẫn ghi nhật ký trên mọi yêu cầu. Ví dụ: chúng tôi có thể giả định rằng DynamoDB phân phối ở mức tối đa 20 triệu yêu cầu mỗi giây chỉ với lưu lượng trong Amazon sẽ không ghi quá nhiều nhật ký. Nhưng thực tế là nó ghi lại mọi yêu cầu để khắc phục sự cố và vì lý do kiểm tra cũng như tuân thủ. Sau đây là một số mẹo ở cấp cao chúng tôi áp dụng ở Amazon để giúp ghi nhật ký hiệu quả hơn ở thông lượng mỗi máy chủ cao hơn:
• Lấy mẫu nhật ký. Thay vì ghi mọi mục, hãy cân nhắc việc ghi mỗi N mục. Mỗi mục cũng bao gồm số lượng mục bị bỏ qua để hệ thống tổng hợp chỉ số có thể ước tính lượng nhật ký thực sự trong chỉ số mà nó tính toán. Các thuật toán lấy mẫu khác như lấy mẫu dự trữ cung cấp nhiều mẫu đại diện hơn. Các thuật toán khác ưu tiên ghi nhật ký các lỗi hoặc yêu cầu chậm so với yêu cầu nhanh, thành công. Tuy nhiên, khi lấy mẫu, thì khả năng giúp khách hàng và khắc phục những lỗi cụ thể có thể giảm đi. Một số yêu cầu tuân thủ không cho phép làm như vậy.
• Chia tải chuỗi hóa và chuyển nhật ký vào một luồng riêng. Đây là một thay đổi dễ dàng và phổ biến.
• Thường xuyên luân chuyển nhật ký. Việc luân chuyển các tệp nhật ký được ghi mỗi giờ có vẻ tiện lợi để bạn không phải xử lý với nhiều tệp, nhưng nếu luân chuyển mỗi phút, thì một số hoạt động sẽ được cải thiện. Ví dụ: tác nhân đọc và nén tệp nhật ký sẽ đọc tệp từ bộ nhớ đệm trang thay vì ổ đĩa, đồng thời CPU cũng như IO từ nhật ký nén và chuyển sẽ được phân phát trong suốt cả giờ thay vì luôn kích hoạt vào cuối mỗi giờ.
• Ghi nhật ký nén sẵn. Nếu tác nhân chuyển nhật ký nén nhật ký trước khi gửi chúng tới một dịch vụ lưu trữ, thì CPU và ổ đĩa hệ thống sẽ hoạt động tối đa theo định kỳ. Bạn có thể giảm thiểu chi phí này và giảm IO ổ đĩa xuống một nửa bằng cách chuyển nhật ký đã nén ra khỏi ổ đĩa. Tuy nhiên, điều này cũng đi kèm với một số rủi ro. Chúng tôi thấy hữu ích khi sử dụng thuật toán nén có thể xử lý các tệp bị cắt trong trường hợp ứng dụng gặp lỗi.
• Ghi vào ramdisk/tmpfs. Dịch vụ có thể dễ dàng ghi nhật ký vào bộ nhớ cho đến khi chúng được chuyển ra khỏi máy chủ thay vì ghi nhật ký vào ổ đĩa. Theo kinh nghiệm của mình, điều này hoạt động hiệu quả nhất với phương pháp luân chuyển nhật ký theo phút chứ không phải theo giờ.
• Tích hợp trong nhật ký. Nếu cần phải xử lý hàng trăm ngàn giao dịch mỗi giây trên một máy duy nhất, thì việc ghi một mục nhật ký trên mỗi yêu cầu có thể rất tốn kém. Tuy nhiên, bạn mất rất nhiều khả năng quan sát khi bỏ qua điều này, do đó, chúng tôi thấy hữu ích khi không tối ưu hóa sớm.
• Theo dõi việc sử dụng tài nguyên. Chúng tôi quan tâm đến việc mình đã đạt đến một số giới hạn mở rộng quy mô ở mức nào. Chúng tôi đo lường IO và CPU mỗi máy chủ và các tác nhân ghi nhật ký đang sử dụng bao nhiêu tài nguyên đó. Khi thực hiện các kiểm tra tải, chúng tôi chạy chúng đủ lâu để có thể chứng minh rằng tác nhân chuyển nhật ký có thể duy trì công suất của chúng tôi.
Triển khai đúng công cụ phân tích nhật ký
Ở Amazon, chúng tôi vận hành các dịch vụ mà chúng tôi ghi nên tất cả chúng tôi đều phải trở thành chuyên gia khắc phục các dịch vụ đó. Điều này bao gồm việc có thể dễ dàng phân tích nhật ký. Chúng tôi có rất nhiều công cụ mà bạn có thể sử dụng, từ phân tích nhật ký cục bộ để xem xét số lượng nhật ký tương đối nhỏ cho đến phân tích nhật ký phân tán để chọn lọc và tổng hợp kết quả từ một lượng nhật ký khổng lồ.
Chúng tôi thấy bạn cần đầu tư vào công cụ và tài liệu vận hành để nhóm phân tích nhật ký. Nếu nhật ký hiện còn nhỏ, nhưng dịch vụ sẽ phát triển theo thời gian, chúng tôi sẽ quan tâm đến thời điểm công cụ hiện tại dừng mở rộng quy mô để có thể đầu tư vào việc áp dụng giải pháp phân tích nhật ký phân tán.
Quy trình phân tích nhật ký có thể yêu cầu kinh nghiệm sử dụng nhiều tiện ích dòng lệnh Linux. Ví dụ: dòng lệnh “tìm địa chỉ IP tạo ra lưu lượng nặng nhất trong nhật ký” khá đơn giản:
cat log | grep -P "^RemoteIp=" | cut -d= -f2 | sort | uniq -c | sort -nr | head -n20
Tuy nhiên, có vô số công cụ khác rất hữu ích để trả lời những câu hỏi phức tạp hơn với nhật ký của chúng tôi, trong đó bao gồm:
• jq: https://stedolan.github.io/jq/
• RecordStream: https://github.com/benbernard/RecordStream
Bạn có thể dùng bất kỳ dịch vụ phân tích đại dữ liệu nào để tiến hành phân tích nhật ký phân tán (ví dụ: Amazon EMR, Amazon Athena, Amazon Aurora và Amazon Redshift). Tuy nhiên, một số dịch vụ được trang bị sẵn hệ thống ghi nhật ký, ví dụ: Amazon CloudWatch Logs.
• Chi tiết chuyên sâu về CloudWatch Logs
• AWS X-Ray: https://aws.amazon.com/xray/
• Amazon Athena: https://aws.amazon.com/athena/
Kết luận
Là chủ sở hữu dịch vụ và nhà phát triển phần mềm, tôi đành lượng lớn thời gian xem xét kết quả của công cụ đo lường: biểu đồ trên bảng thông tin, từng tệp nhật ký, đồng thời sử dụng các công cụ phân tích nhật ký phân tán như CloudWatch Logs Insights. Đó là một số công việc yêu thích của tôi. Khi cần nghỉ ngơi sau khi hoàn thành một số nhiệm vụ thách thức, tôi sẽ thư giãn và thưởng cho mình bằng cách khám phá một số nhật ký. Tôi bắt đầu bằng các câu hỏi như “vì sao chỉ số này lại tăng vọt ở đây?” hay “độ trễ của hoạt động này có thể thấp hơn không?” Khi câu hỏi của tôi đi vào bế tắc, tôi thường tìm một số phép đo sẽ hữu ích trong mã nên tôi thêm công cụ đo lường, phép kiểm thử và gửi đánh giá mã cho thành viên nhóm.
Mặc dù nhiều chỉ số đi kèm với dịch vụ được quản lý mà chúng tôi sử dụng, nhưng chúng tôi cần dành rất nhiều tâm huyết cho việc đo lường dịch vụ của chính mình để hiểu rõ mình cần gì để vận hành chúng hiệu quả. Trong các sự kiện vận hành, chúng tôi cần xác định nhanh vì sao chúng tôi gặp vấn đề và chúng tôi có thể làm gì để khắc phục vấn đề đó. Việc có chỉ số phù hợp trên bảng thông tin đóng vai trò sống còn, giúp chúng tôi có thể chẩn đoán nhanh chóng. Ngoài ra, vì chúng tôi luôn thay đổi dịch vụ, bổ sung tính năng mới và thay đổi cách tương tác với thành phần phụ thuộc, nên việc cập nhật và thêm công cụ đo lường phù hợp sẽ diễn ra liên tục.
Các liên kết
• “Nhìn vào dữ liệu của bạn” của John Rauser, cựu nhân viên Amazon: https://www.youtube.com/watch?v=coNDCIMH8bk (ở phút 13:22, anh in nhật ký để xem dễ hơn)
• “Đầu tư vào vấn đề bất thường” của John Rauser, cựu nhân viên Amazon: https://www.youtube.com/watch?v=-3dw09N5_Aw
• “Cách con người xem dữ liệu” của John Rauser, cựu nhân viên Amazon: https://www.youtube.com/watch?v=fSgEeI2Xpdc
• https://www.akamai.com/uk/en/about/news/press/2017-press/akamai-releases-spring-2017-state-of-online-retail-performance-report.jsp
Giới thiệu về tác giả
David Yanacek là Kỹ sư chính cấp cao làm việc với AWS Lambda. David là nhà phát triển phần mềm tại Amazon từ năm 2006, trước đây đã làm việc với Amazon DynamoDB và AWS IoT, cũng như các khung dịch vụ web nội bộ và các hệ thống tự động hóa nghiệp vụ nhóm. Một trong những hoạt động yêu thích của David tại nơi làm việc là thực hiện phân tích nhật ký và sàng lọc các số liệu hoạt động để tìm cách làm cho hệ thống vận hành ngày càng trơn tru hơn.