Trong thế giới công nghệ ngày nay, tốc độ là chìa khóa của sự thành công. Tại LinkedIn, nơi hàng tỷ yêu cầu từ người dùng được xử lý mỗi ngày trên nhiều nền tảng khác nhau, các kĩ sư tại Linkedin luôn tìm cách để cải thiện trải nghiệm người dùng. Một trong những yếu tố quan trọng nhất là thời gian tải trang - yếu tố có ảnh hưởng trực tiếp đến sự hài lòng của người dùng và hiệu suất của nền tảng. Để cải thiện trải nghiệm người dùng và giảm thiểu thời gian phản hồi, họ đã tích hợp một giải pháp mã hóa mới vào Rest.li, giúp giảm đáng kể độ trễ và tối ưu hóa việc sử dụng tài nguyên.
Tags: #system design, #protocol buffers, #linkedinTrong thế giới công nghệ ngày nay, tốc độ là chìa khóa của sự thành công. Tại LinkedIn, nơi hàng tỷ yêu cầu từ người dùng được xử lý mỗi ngày trên nhiều nền tảng khác nhau, các kĩ sư tại Linkedin luôn tìm cách để cải thiện trải nghiệm người dùng. Một trong những yếu tố quan trọng nhất là thời gian tải trang - yếu tố có ảnh hưởng trực tiếp đến sự hài lòng của người dùng và hiệu suất của nền tảng. Để cải thiện trải nghiệm người dùng và giảm thiểu thời gian phản hồi, họ đã tích hợp một giải pháp mã hóa mới vào Rest.li, giúp giảm đáng kể độ trễ và tối ưu hóa việc sử dụng tài nguyên.
Khi mới ra đời, Rest.li sử dụng JSON làm định dạng tuần tự hóa mặc định. JSON đã phục vụ tốt trong một thời gian dài. Nó dễ đọc cho người lập trình, được hỗ trợ rộng rãi trong nhiều ngôn ngữ lập trình. Nhưng dần dần, JSON bắt đầu bộc lộ những hạn chế của mình:
Họ đã bắt đầu đi tìm kiếm một giải pháp giải quyết được các thách thức này, một số tiêu chí họ đặt ra cho “ứng viên” thay thế được JSON là:
Sau khi đánh giá kỹ lưỡng nhiều ứng viên như Flatbuffers, Cap'n'Proto, SMILE, MessagePack, CBOR, và Kryo, họ đã xác định Protobuf là lựa chọn tốt nhất vì nó hoạt động hiệu quả nhất với các tiêu chí trên.
Hãy tưởng tượng bạn đang cố gắng ghép một mảnh ghép hình tròn vào một lỗ vuông. Đó chính xác là thách thức mà chúng tôi phải đối mặt khi tích hợp Protobuf vào Rest.li. Tại sao ư? Bởi vì Rest.li và Protobuf có cách "suy nghĩ" rất khác nhau về dữ liệu.Rest.li là một kẻ tự do. Nó không quan tâm đến schema và chỉ làm việc với DataMaps và DataLists. Nó sử dụng PDL (Protocol Definition Language) để mô hình hóa dữ liệu, nhưng PDL không có khái niệm về số thứ tự của trường dữ liệu. Ngược lại, Protobuf là một người thích trật tự. Nó cần dữ liệu được định nghĩa rõ ràng và mỗi trường dữ liệu phải có một số thứ tự cụ thể thường được xác định rõ trong Proto Schema.Để giải quyết vấn đề này, họ đã tạo ra "bảng ký hiệu" (symbol tables) - một bản đồ hai chiều kết nối các fields/value enum trong PDL với các số nguyên. Đây chính là chìa khóa để họ có thể sử dụng Protobuf mà không cần thay đổi cách Rest.li hoạt động.
Thách thức tiếp theo mà họ phải đối mặt là làm thế nào để tạo ra các bảng ký hiệu (symbol tables). Để giảm bớt công việc cho các dịch vụ backend, họ đã chọn phương pháp tạo và trao đổi bảng ký hiệu trong thời gian chạy (runtime), như được minh họa dưới đây:
Họ đã áp dụng hai chiến lược khác nhau để quản lý bảng ký hiệu, tùy thuộc vào loại ứng dụng:
Trong quá trình khởi động dịch vụ (Service BootUp)
symbolTable
.Giao tiếp giữa Client và Server
symbolTable
. Bảng ký hiệu nhận được sẽ được lưu trữ vào bộ nhớ cache để sử dụng trong các yêu cầu sau này, giảm thiểu số lần yêu cầu đến server.Content-Type: application/x-protobuf2; symbol-table=mySymbolTable-v1
Phương pháp này rất linh hoạt và tự động, giúp tối ưu hóa việc truyền tải dữ liệu bằng cách giảm kích thước payload và đảm bảo đồng bộ hóa giữa các phiên bản của dịch vụ. Tuy nhiên, do cần phải yêu cầu bảng ký hiệu từ server trong lần khởi động đầu tiên, phương pháp này có thể gây ra độ trễ ban đầu. Điều này có thể không phù hợp với các ứng dụng web/mobile yêu cầu thời gian khởi động nhanh và trải nghiệm người dùng mượt mà.
Đây là cách tiếp cận "chuẩn bị trước", tương tự như việc mang theo một cuốn từ điển khi bạn đi du lịch. Phương pháp này giúp giảm thiểu độ trễ và áp lực cho server trong quá trình triển khai các phiên bản mới của API.
Phương pháp này giúp đảm bảo hiệu năng ổn định và giảm thiểu rủi ro về độ trễ hoặc sự cố trong quá trình khởi động hoặc nâng cấp ứng dụng, đặc biệt hữu ích khi ứng dụng cần giao tiếp với các API có thể thay đổi thường xuyên.
Việc tích hợp Protobuf vào Rest.li đã giúp giảm độ trễ lên đến 60% đối với các dịch vụ có payload lớn. Con số này không chỉ là số liệu thống kê - chúng đại diện cho trải nghiệm nhanh hơn, mượt mà hơn cho hàng triệu người dùng LinkedIn trên toàn cầu. Dưới đây là biểu đồ so sánh độ trễ giữa Protobuf và JSON khi các server chịu tải nặng.
Việc sử dụng Protobuf thay vì JSON đã mang lại những cải tiến hiệu suất đáng kể, tạo ra những khoản tiết kiệm thực sự ở quy mô kỹ thuật của LinkedIn. Quá trình triển khai thay đổi này bằng các kỹ thuật như bảng ký hiệu (symbol tables) và cấu hình theo từng giai đoạn đã giúp cho việc chuyển đổi trở lên dễ dàng. Nhờ đó, họ đã đạt được những lợi ích này với rất ít gián đoạn đối với hoạt động kỹ thuật và kinh doanh.