-
Design Pattern
- Singleton Design Pattern
- Factory Design Pattern
- Factory Method Design Pattern
- Abstract Factory Design Pattern
- Builder Design Pattern
- Prototype Design Pattern
- Object Pool Design Pattern
- Chain of Responsibility Design Pattern
- Command Design Pattern
- Interpreter Design Pattern
- Iterator Design Pattern
- Mediator Design Pattern
- Memento Design Pattern
- Observer Design Pattern
- Observer Design Pattern - Xử Lý Exception
- Strategy Design Pattern
- Template Method Design Pattern
- Visitor Design Pattern
- Null Object Design Pattern
- Adapter Design Pattern
- Bridge Design Pattern
- Composite Design Pattern
- Decorator Design Pattern
- Flyweight Design Pattern
- Proxy Design Pattern
- S.O.L.I.D
- Clean code
- Lập trình socket
- Java Core
- Multi-Thread
- Spring
- Java Web
- Memory Caching
- Message Queue
- DevOps
- Xây dựng một nền tảng
- MongoDB
- MySQL timestamp
- Properties vs yaml
- Kotlin
- Lập Trình Machine Learning với PyTorch
- Mã Nguồn Mở
- Ezy HTTP
- Free Chat
- Một số kinh nghiệm với Git
- Review cho đồng nghiệp!
- Kinh nghiệm phát triển dự án phức tạp, nhiều người - Tuân thủ
- Kinh nghiệm phát triển dự án phức tạp, nhiều người - Lựa chọn người đi cùng
- Ngành công nghiệp phần mềm tại Việt Nam - Mới chỉ là bắt đầu.
- Ngành công nghiệp phần mềm tại Việt Nam - Dây chuyền sản xuất.
- Ngành công nghiệp phần mềm tại Việt Nam - Thị trường
- Ngành công nghiệp phần mềm tại Việt Nam - Công ăn việc làm
- Setup Dev Environment
- Hello World
- Create a Server Project
- Handle Client Requests
- Using ezyfox-server-csharp-client
- Using ezyfox-es6-client
- Client React.js Interaction
- Build And Deploy In Local
- Tham gia phát triển open source!
- Buôn có bạn, bán có phường
- Đam mê đi đâu rồi?
- Giữa lửa đam mê!
- Tương lai nào cho tester? Thay đổi để dẫn đầu xu thế!
- Tương lai nào cho tester? - Khi thế sự đổi thay!
- Tương lai nào cho lập trình viên? Khi không có hệ quy chiếu!
- Tương lai nào cho lập trình viên - Làm đến bao nhiêu tuổi?
- Tương lai nào cho lập trình viên? Có làm giàu được không?
- Tương lai nào cho lập trình viên? Có cân bằng cuộc sống được không?
- Tương lai nào cho lập trình viên - Nhảy việc đến khi nào?
- Tương lai nào cho lập trình viên - Con đường sự nghiệp (Career path)!
- Tương lai nào cho lập trình viên - Tổng kết lại!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn sơ cấp (Junior)!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn trung cấp (Intermediate)!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn lành nghề (Senior)!
- Giai đoạn lành nghề (Senior) - Giữa những hoang mang!
- Giai đoạn lành nghề (Senior) - Phân hoá trong doanh nghiệp!
- Con đường sự nghiệp cho lập trình viên - Trở thành chuyên gia (Expert)!
- Con đường sự nghiệp cho lập trình viên - Trở thành người ảnh hưởng (Influencer)!
- Các giai đoạn phát triển của lập trình viên - Tổng kết lại!
- Metaverse - Câu chuyện 10 nghìn CCU (Người tham gia đồng thời)
- Metaverse có khả thi ở Việt Nam?
- Lựa chọn nghề nghiệp - DevOps!
- Lựa chọn nghề nghiệp - Project Manager (PM)!
- Lựa chọn nghề nghiệp - Data Engineer!
- Lựa chọn nghề nghiệp - BackEnd Engineer!
- “Talk is cheap. Show me the code” ― Linus Torvalds
- Lựa chọn nghề nghiệp - Web Front-End Engineer!
- Lựa chọn nghề nghiệp - Mobile Engineer!
- Lựa chọn nghề nghiệp - Game Engineer!
- Lựa chọn nghề nghiệp - Product Owner!
- Tuổi trẻ cần đột phá!
- Tuổi trẻ cần sự đồng cảm!
- Tuổi trẻ - điều đáng sợ đầu tiên là gì?
- Tuổi trẻ - Điều đáng sợ thứ 2 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 3 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 4 là gì?
- Nếu tận dụng hết năng lực thì sẽ thế nào?
- Tuổi trẻ - Điều đáng sợ thứ 5 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 6 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 7 là gì?
- Tuổi trẻ - ham học hỏi là như thế nào?
- Đầu tư cho bản thân là gì?
- Học chủ động!
- Có nên quay lại công ty cũ?
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 1)
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 2)
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 3)
- Tự học
- Học tập tại doanh nghiệp
- Học tại trung tâm
- Cách đọc sách kỹ thuật hiệu quả
- Học trong một tổ chức mã nguồn mở.
- Câu chuyện lập trình viên - Công việc đầu tiên
- Câu chuyện lập trình viên - Mức lương đầu tiên
- Câu chuyện lập trình viên - 2018
- Định hướng là gì?
- Wordpress nguy hiểm thế nào?
- Danh sách 10 trung tâm đào tạo trình uy tín, chất lượng ở Hà Nội
Khó hiểu nhưng gọn nhẹ!
Protobuf hay Protocol buffer là một cách thức pack và unpack dữ liệu do các kỹ sư của Google sáng chế ra, mục tiêu của nó là để giảm số lượng byte cần thiết để biểu diễn một gói tin, từ đó tăng tốc độ gửi nhận qua network vốn dĩ vẫn chậm chạp. Và cho đến thời điểm này, protobuf vẫn là một trong những giao thức nhẹ nhàng và tiết kiệm được nhiều byte nhất. Mục tiêu thì đơn giản nhưng việc hiểu được cơ chế bên trong của Protobuf lại không hề đơn giản, nhất là khi chúng ta vẫn thường chỉ tiếp xúc với các file .proto, các công cụ gen ra file code và các lớp builder. Trong bài này, chúng ta sẽ cùng đào sâu vào lõi của protobuf nhé.
Bài toán thực tế
Hãy tưởng tưởng, à không cần tưởng tượng, chúng ta đang cần gửi con số int: 300 qua socket, ồ thật đơn giản chỉ cần gửi 4 bytes:
[0, 0, 1, 44]
Như thế này đi thôi đúng không? Nhưng nhìn lại 1 chút, có cái gì đó không ổn ở đây? hình như thừa 2 số 0 ở đầu? Đúng vậy, chúng ta không cần thiết phải dùng đến 4 bytes để mô tả số 300, chúng ta chỉ cần dùng tối đa 2 bytes là 1 và 44 là đủ.
Ồ, nhưng trong thực tế chẳng bao giờ chúng ta lại đi gửi 1 con số 300 vô nghĩa qua socket cả, thường thì chúng ta sẽ gửi một message kiểu:
[300, 100]
Ý nghĩa ở đây là: trừ 100đ trong tài khoản của user có id là 300. Vậy thì phải mô tả cái message này kiểu gì giờ? Nếu mà để kiểu
[1, 44, 100]
Lúc đọc chúng ta sẽ hiểu nhầm là số 76900, phải cần một cái gì đó thể phân tách ra được thành 2 số 300 và 100. Lúc này một kỹ sư đã có ý tưởng và Protobuf ra đời.
Ý tưởng ban đầu
Ý tưởng của protobuf rất đơn giản, đó là sử dụng 1 bit đầu tiên của 1 byte để đánh dấu rằng có dữ liệu ở byte tiếp theo không, nghĩa là cứ 1 byte, chúng ta lại mất 1 bit để để đánh dấu và chỉ có 7 bit cho phần dữ liệu mà thôi. Ồ vậy đối với kiểu dữ liệu string thì sao, cứ mỗi 1 byte cũng lại mất 1 bit à? Không phải, đối với từng kiểu dữ liệu lại có đối ứng khác nhau:
- Đối với kiểu dữ liệu số nguyên (int, long): có thể mỗi byte sẽ cần mất 1 bit
- Đối với kiểu dữ liệu kiểu string: phần độ dài của string (int) có thể mỗi byte sẽ cần mất 1 bit, còn phần nội dung sẽ được dữ nguyên
- Đối với kiểu dữ liệu mảng (array, list) hay map: phần size int) có thể mỗi byte sẽ cần mất 1 bit, còn phần nội dung sẽ tuần theo 1 và 2
Cơ chế hoạt động
Ví dụ con số 300 sẽ có dãy bit là: 100101100
, viết ở dạng 2 byte sẽ là:
00000001 00101100
Viết ở dạng 7 bit chúng ta có:
0000010 0101100
Đảo ngược lại chúng ta có:
0101100 0000010
Chúng ta có thể thấy dãy bit có 2 phần, vậy ta sẽ bổ sung bit 1 vào 7 bit đầu (đánh dấu là có dữ liệu ở phía sau), và bit 0 vào 7 bit cuối (không còn dữ liệu ở phía sau nữa), và chúng ta có
10101100 00000010
file.proto
Chúng ta có thể thấy, protobuf chỉ đơn thuần là các byte[] nằm cạnh nhau, và nó chẳng thể nào biết kiểu dữ liệu là gì để mà parse ra, chính vì vậy mà nó cần file.proto để định nghĩa kiểu. Ví dụ chúng ta có file proto:
// UpdateUserMoney.proto
int32 userId = 1; // sẽ đọc tối đa 4 bytes
int32 balance = 2; // sẽ đọc tối đa 4 bytes
Để đọc được mảng byte [2, 172, 2, 100]
ra thành đối tượng:
class UpdateUserMoney {
int userId;
int balance;
}
- Bước 1: khởi tạo đối tượng
UpdateUserMoney obj = new UpdateUserMoney()
- Bước 1: đọc byte đầu tiên là
2
chúng ta thấy 2 được biểu diễn dưới dạng bit là00000010
vậy không có thêm byte nào tiếp theo, giá trị chúng ta nhận được sẽ là 2, vậy đối tượng của chúng ta sẽ có 2 trường - Bước 2: đọc byte
172
dưới dạng bit10101100
chúng ta thấy có bit 1 ở đầu, vậy cần phải đọc tiếp, trước khi đọc tiếp bỏ số 1 đi, lưu lại 7 bit0101100
- Bước 3: đọc bye
2
dưới dạng bit00000010
chúng không thấy có bit 1 ở đầu, vậy dừng lại việc đọc - Bước 4: ghép 2 dãy bít ta được
00000010 0101100
, đọc thành số ta được 300 - Bước 5: gán 300 vào userId: `obj.setUserId(300)
- Bước 6: Đọc 100 thành bit chúng ta có
01100100
, không có bit 1 ở đầu vậy chúng ta có giá trị 100 - Bước 7: set 100 vào balance:
obj.setBalance(100)
- Bước 8: không còn byte nào nữa kết thục tại đây và trả về
obj
Protobuf cũng cho phép chúng ta chưa cần thiết phải parse ra kiểu cụ thể, chúng ta có thể đọc ra giá trị ở runtime, bằng cách thêm optional
khi khai báo trường dữ liệu:
// UpdateUserMoney.proto
optional int32 userId = 1; // sẽ đọc tối đa 4 bytes
optional int32 balance = 2; // sẽ đọc tối đa 4 bytes
Ví dụ
Ở đây mình chỉ làm ví dụ đơn giản để serialize và deserialize 1 số int thành byte array và ngược lại thôi nhé:
import java.nio.ByteBuffer;
public class ProtobufExample {
public static void main(String[] args) {
final int value = 300;
final byte[] bytes = serialize(300);
System.out.println("serialize of " + value + ": " + toString(bytes));
System.out.println("deserialize: " + deserialize(bytes));
}
private static int deserialize(byte[] bytes) {
int answer = 0;
for(int i = 0 ; i < bytes.length ; ++i) {
answer += (bytes[i] & 0x7F) << i * 7;
}
return answer;
}
private static byte[] serialize(int value) {
final byte[] valueBytes = ByteBuffer.allocate(4).putInt(value).array();
int byteCount = 4;
for (byte valueByte : valueBytes) {
if ((valueByte & 0xFF) != 0) {
break;
}
--byteCount;
}
final ByteBuffer byteBuffer = ByteBuffer.allocate(byteCount);
int remainValue = value;
for(int i = 0 ; i < byteCount - 1 ; ++i) {
// 0x80 = 10000000
byteBuffer.put((byte)(0x80 | (0x7F & remainValue)));
remainValue >>= 7;
}
byteBuffer.put((byte)remainValue);
return byteBuffer.array();
}
private static String toString(byte[] array) {
final StringBuilder builder = new StringBuilder("[");
for(int i = 0 ; i < array.length ; ++i) {
final ByteBuffer buffer = ByteBuffer.allocate(4).put(new byte[] { 0, 0, 0, array[i]});
buffer.flip();
builder.append(buffer.getInt());
if(i < array.length - 1) {
builder.append(", ");
}
}
builder.append("]");
return builder.toString();
}
}
Kết quả chúng ta nhận được sẽ là:
serialize of 300: [172, 2]
deserialize: 300
Tham khảo
-
Design Pattern
- Singleton Design Pattern
- Factory Design Pattern
- Factory Method Design Pattern
- Abstract Factory Design Pattern
- Builder Design Pattern
- Prototype Design Pattern
- Object Pool Design Pattern
- Chain of Responsibility Design Pattern
- Command Design Pattern
- Interpreter Design Pattern
- Iterator Design Pattern
- Mediator Design Pattern
- Memento Design Pattern
- Observer Design Pattern
- Observer Design Pattern - Xử Lý Exception
- Strategy Design Pattern
- Template Method Design Pattern
- Visitor Design Pattern
- Null Object Design Pattern
- Adapter Design Pattern
- Bridge Design Pattern
- Composite Design Pattern
- Decorator Design Pattern
- Flyweight Design Pattern
- Proxy Design Pattern
- S.O.L.I.D
- Clean code
- Lập trình socket
- Java Core
- Multi-Thread
- Spring
- Java Web
- Memory Caching
- Message Queue
- DevOps
- Xây dựng một nền tảng
- MongoDB
- MySQL timestamp
- Properties vs yaml
- Kotlin
- Lập Trình Machine Learning với PyTorch
- Mã Nguồn Mở
- Ezy HTTP
- Free Chat
- Một số kinh nghiệm với Git
- Review cho đồng nghiệp!
- Kinh nghiệm phát triển dự án phức tạp, nhiều người - Tuân thủ
- Kinh nghiệm phát triển dự án phức tạp, nhiều người - Lựa chọn người đi cùng
- Ngành công nghiệp phần mềm tại Việt Nam - Mới chỉ là bắt đầu.
- Ngành công nghiệp phần mềm tại Việt Nam - Dây chuyền sản xuất.
- Ngành công nghiệp phần mềm tại Việt Nam - Thị trường
- Ngành công nghiệp phần mềm tại Việt Nam - Công ăn việc làm
- Setup Dev Environment
- Hello World
- Create a Server Project
- Handle Client Requests
- Using ezyfox-server-csharp-client
- Using ezyfox-es6-client
- Client React.js Interaction
- Build And Deploy In Local
- Tham gia phát triển open source!
- Buôn có bạn, bán có phường
- Đam mê đi đâu rồi?
- Giữa lửa đam mê!
- Tương lai nào cho tester? Thay đổi để dẫn đầu xu thế!
- Tương lai nào cho tester? - Khi thế sự đổi thay!
- Tương lai nào cho lập trình viên? Khi không có hệ quy chiếu!
- Tương lai nào cho lập trình viên - Làm đến bao nhiêu tuổi?
- Tương lai nào cho lập trình viên? Có làm giàu được không?
- Tương lai nào cho lập trình viên? Có cân bằng cuộc sống được không?
- Tương lai nào cho lập trình viên - Nhảy việc đến khi nào?
- Tương lai nào cho lập trình viên - Con đường sự nghiệp (Career path)!
- Tương lai nào cho lập trình viên - Tổng kết lại!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn sơ cấp (Junior)!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn trung cấp (Intermediate)!
- Con đường sự nghiệp cho lập trình viên - Giai đoạn lành nghề (Senior)!
- Giai đoạn lành nghề (Senior) - Giữa những hoang mang!
- Giai đoạn lành nghề (Senior) - Phân hoá trong doanh nghiệp!
- Con đường sự nghiệp cho lập trình viên - Trở thành chuyên gia (Expert)!
- Con đường sự nghiệp cho lập trình viên - Trở thành người ảnh hưởng (Influencer)!
- Các giai đoạn phát triển của lập trình viên - Tổng kết lại!
- Metaverse - Câu chuyện 10 nghìn CCU (Người tham gia đồng thời)
- Metaverse có khả thi ở Việt Nam?
- Lựa chọn nghề nghiệp - DevOps!
- Lựa chọn nghề nghiệp - Project Manager (PM)!
- Lựa chọn nghề nghiệp - Data Engineer!
- Lựa chọn nghề nghiệp - BackEnd Engineer!
- “Talk is cheap. Show me the code” ― Linus Torvalds
- Lựa chọn nghề nghiệp - Web Front-End Engineer!
- Lựa chọn nghề nghiệp - Mobile Engineer!
- Lựa chọn nghề nghiệp - Game Engineer!
- Lựa chọn nghề nghiệp - Product Owner!
- Tuổi trẻ cần đột phá!
- Tuổi trẻ cần sự đồng cảm!
- Tuổi trẻ - điều đáng sợ đầu tiên là gì?
- Tuổi trẻ - Điều đáng sợ thứ 2 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 3 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 4 là gì?
- Nếu tận dụng hết năng lực thì sẽ thế nào?
- Tuổi trẻ - Điều đáng sợ thứ 5 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 6 là gì?
- Tuổi trẻ - Điều đáng sợ thứ 7 là gì?
- Tuổi trẻ - ham học hỏi là như thế nào?
- Đầu tư cho bản thân là gì?
- Học chủ động!
- Có nên quay lại công ty cũ?
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 1)
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 2)
- Làm cho startup (công ty nhỏ) hay làm cho công ty lớn? (Phần 3)
- Tự học
- Học tập tại doanh nghiệp
- Học tại trung tâm
- Cách đọc sách kỹ thuật hiệu quả
- Học trong một tổ chức mã nguồn mở.
- Câu chuyện lập trình viên - Công việc đầu tiên
- Câu chuyện lập trình viên - Mức lương đầu tiên
- Câu chuyện lập trình viên - 2018
- Định hướng là gì?
- Wordpress nguy hiểm thế nào?
- Danh sách 10 trung tâm đào tạo trình uy tín, chất lượng ở Hà Nội