Trong cuộc họp cập nhật dự án gần đây, team tôi thảo luận về việc dùng serialization để gửi dữ liệu qua lại giữa các ứng dụng.
Một kỹ sư muốn tham gia sâu hơn vào dự án phần mềm nói với tôi rằng họ không quen với thuật ngữ này.
Dễ dàng bỏ lỡ các quy trình thiết yếu như thế này mà không gặp cho đến khi đào sâu vào dự án lớn. Đối với người này, cũng như tôi tại một thời điểm.
Vì vậy tôi muốn viết về nó. Tôi đã giúp đồng nghiệp hiểu về serialization hôm đó, và hôm nay bạn sẽ học về nó.
Serialization là gì?
Serialization là quá trình một service nhận một cấu trúc dữ liệu, ví dụ dictionary trong Python, gói gọn nó, và truyền đến service khác để đọc. Đó là định nghĩa đơn giản.
Hãy tưởng tượng tôi cần gửi tin nhắn cho ai đó. Tôi viết text trên một bức tranh ghép ép đã lắp ráp. Tôi tháo các mảnh ghép, thêm hướng dẫn lắp ráp lại, và gửi đi.
Người nhận lấy các mảnh ghép, lắp lại tất cả, và bây giờ họ có tin nhắn của tôi.
Định nghĩa kỹ thuật hơi thú vị hơn. Tóm lại, serialization là quá trình chuyển đổi đối tượng dữ liệu thành byte stream (luồng byte), và lưu trạng thái đối tượng để lưu trữ trên ổ đĩa hoặc truyền qua mạng. Điều này giảm dung lượng lưu trữ cần thiết và làm cho việc truyền thông tin qua mạng dễ dàng hơn.
Marshaling và Serialization - khác nhau như thế nào?
Quy trình marshaling có thể nhảy vào đầu. Marshaling là quá trình biến đổi biểu diễn bộ nhớ của đối tượng thành dạng phù hợp để truyền tải.
Mặc dù marshaling và serialization gần như đồng nghĩa, có một khác biệt quan trọng. Ví dụ, khi tạo chương trình Golang đọc dữ liệu JSON vào cấu trúc dữ liệu Golang, bạn có thể dùng marshaling dịch giá trị key JSON thành giá trị key Golang.
Khác biệt là marshaling có thể dùng để dịch dữ liệu. Ngược lại, serialization gửi hoặc lưu dữ liệu trong byte stream và lắp ráp lại nó ở dạng gốc. Cả hai đều làm serialization, nhưng có khác biệt về ý định trong hai quy trình này.
Bạn có thể thấy struct tôi tạo để tương tác dữ liệu Twitter dưới đây như ví dụ marshaling hoạt động. Trong Golang, bạn có thể đưa ra gợi ý gọi là tags, dễ dàng chuyển đổi đối tượng này thành dữ liệu JSON dùng service marshaling tích hợp của Golang.
Endianness là gì?
Tôi cũng muốn nhẹ nhàng nhắc đến endianness. Endianness là thuật ngữ mô tả thứ tự byte trong bộ nhớ.
Bạn có thể coi bộ nhớ như khối nơi bit dữ liệu được lưu. Để serialization hoạt động, byte stream cần truyền kiểu dữ liệu bất kể endianness thay đổi từ hệ thống này sang hệ thống khác.
Bạn có thể thấy sự khác biệt little-endian và big-endian dưới đây. Rất quan trọng endianness khớp từ hệ thống này sang hệ thống khác hoặc được chuyển đổi, vì không phải hệ thống nào cũng sắp xếp bit theo cùng cách.
Trường hợp sử dụng Serialization
Trường hợp của chúng tôi tận dụng tối đa các tính năng này. Chúng tôi dự định lấy thông tin từ phần cứng quét, gói thông tin đó thành byte stream, gửi qua mạng đến service khác sẽ tái cấu trúc dữ liệu.
Quá trình đảo ngược serialization và tái cấu trúc dữ liệu về dạng gốc gọi là deserialization.
Có trường hợp dùng khác. Ví dụ, REST API hoặc giao thức nhắn tin như AMQP dùng serialization nén và gửi dữ liệu.
AMQP là giao thức nhắn tin gửi message đến AMQP broker, service nhận "nghe" broker này chờ message. Backend engineer có thể biết tốt, vì thường dùng gửi dữ liệu qua lại trong hệ thống phân tán.
Nhiều ngôn ngữ lập trình bao gồm khả năng khởi động serialization dễ dàng. Vì vậy đây là chủ đề language-agnostic (ngôn ngữ trung lập).
Ví dụ Serialization
Cho ví dụ nhanh. Code này dùng thư viện kombu gửi message qua AMQP. Dùng để gửi message từ gói phần mềm này sang gói khác qua mạng. Code cho service gửi message đến AMQP broker:
def send_message(self, payload, sender_serializer):
...
try:
producer.publish(
{'payload': message},
...
serializer = 'json',
...
)
return
Chú ý phương thức publish. Chúng ta truyền phương thức serialization làm tham số để thư viện biết cách serialize dữ liệu truyền vào.
Tin nhắn dữ liệu chuyển thành byte stream, nhìn như chuỗi dài chữ và số, và gửi message.
Service tương ứng dùng cùng phương thức serialization tái cấu trúc dữ liệu về trạng thái gốc. Đây là tính năng quan trọng vì chúng ta tạo bộ công cụ cần gửi message cho nhau để hoạt động.
Định dạng dữ liệu Serialization
Tôi dùng JSON cho serialization bất cứ khi nào nhiệm vụ yêu cầu. Tuy nhiên, bạn cũng có thể dùng một số định dạng khác.
JSON có nhiều overhead, nhưng độ đọc được bởi con người làm nó lý tưởng cho tôi. Bạn cũng có thể dùng Protobufs, YAML, hoặc XML. Đó chỉ là một số định dạng đối tượng dữ liệu bạn có thể dùng.
Kết luận
Tôi vui vì đã viết ra điều này. Tôi ngừng nghĩ về nó, và hy vọng ai đó học được gì đó từ nó.
Serialization trở nên thiết yếu khi bạn lắp ráp pipeline giao tiếp. Tốt khi biết chủ đề này để tự tin tiếp cận bất kỳ công cụ nào bạn dùng với kiến thức nền tảng phù hợp.
-George