ช่วงนี้เริ่มให้ทีมปรับ service บางตัวเพื่อเพิ่ม performance ในการใช้งาน service ให้รองรับการใช้งานในปริมาณที่เยอะ เลยมีการใช้งาน Protocol Buffers บทความนี้เลยเอามาเขียนแนะนำนิดหน่อย

Protocol Buffers คือ อะไร

Protocol Buffers (หรือเรียกสั้นๆ ว่า Protobuf) คือ รูปแบบการเข้ารหัสข้อมูลแบบ binary ที่พัฒนาโดย Google ใช้สำหรับการ serializing structured data คล้ายกับ JSON หรือ XML แต่มีขนาดเล็กกว่า เร็วกว่า และมีประสิทธิภาพมากกว่า เอาไว้ รับ-ส่ง จากที่หนึ่งไปอีกที่หนึ่ง

ProtoBuf มักใช้ในระบบที่ต้องการประสิทธิภาพสูง เช่น microservices, gRPC, การสื่อสารระหว่าง services ต่างๆ หรือการจัดเก็บข้อมูลที่ต้องการความเร็วและประหยัดพื้นที่

Protobuf ต้องมีไฟล์ .proto ซึ่งเป็น message definition อารมณ์คล้ายๆ interface ไว้เป็น contract กลางว่าเราจะ รับ-ส่ง ข้อมูลแบบไหน

จุดเด่นของ Protocol Buffers

  • ประสิทธิภาพสูง - ข้อมูลถูกเข้ารหัสเป็น binary format ทำให้มีขนาดเล็กและประมวลผลเร็วกว่า JSON หรือ XML มาก
  • รองรับหลายภาษา - มี compiler ที่สามารถสร้าง code สำหรับหลายภาษาโปรแกรมมิ่ง เช่น Java, Python, C++, Go, JavaScript และอื่นๆ
  • มี Schema ที่ชัดเจน - คุณต้องกำหนดโครงสร้างข้อมูล (schema) ไว้ล่วงหน้าในไฟล์ .proto ทำให้ข้อมูลมีโครงสร้างที่แน่นอนและตรวจสอบได้
  • รองรับการพัฒนาแบบ backward/forward compatible - คุณสามารถเพิ่มหรือลบฟิลด์ได้โดยที่ไม่ทำให้ code เก่าพัง

ตัวอย่างการใช้งาน

เรามาดูตัวอย่างการใช้ Protocol Buffers สำหรับระบบ chat กัน

1. กำหนด Schema (.proto file)

syntax = "proto3";

package chat;

// ข้อความ chat
message ChatMessage {
  string message_id = 1;      // ID ของข้อความ
  string sender_id = 2;       // ID ของผู้ส่ง
  string receiver_id = 3;     // ID ของผู้รับ
  string content = 4;         // เนื้อหาข้อความ
  int64 timestamp = 5;        // เวลาที่ส่ง (Unix timestamp)
  MessageType type = 6;       // ประเภทข้อความ
  MessageStatus status = 7;   // สถานะข้อความ
}

// ประเภทข้อความ
enum MessageType {
  TEXT = 0;
  IMAGE = 1;
  VIDEO = 2;
  FILE = 3;
}

// สถานะข้อความ
enum MessageStatus {
  SENT = 0;
  DELIVERED = 1;
  READ = 2;
}

// ข้อมูลผู้ใช้
message User {
  string user_id = 1;
  string username = 2;
  string avatar_url = 3;
  bool is_online = 4;
}

// การพิมพ์ข้อความ (typing indicator)
message TypingIndicator {
  string user_id = 1;
  string chat_id = 2;
  bool is_typing = 3;
}

chat.proto

  1. การใช้งานใน Go
package main

import (
    "fmt"
    "time"
    pb "protobuf"  // import protobuf file
    "google.golang.org/protobuf/proto"
)

func createChatMessage(senderID, receiverID, content string) *pb.ChatMessage {
    return &pb.ChatMessage{
        MessageId:  fmt.Sprintf("msg_%d", time.Now().UnixMilli()),
        SenderId:   senderID,
        ReceiverId: receiverID,
        Content:    content,
        Timestamp:  time.Now().Unix(),
        Type:       pb.MessageType_TEXT,
        Status:     pb.MessageStatus_SENT,
    }
}

func main() {
    // สร้างข้อความ
    msg := createChatMessage(
        "user123",
        "user456",
        "สวัสดีครับ! ว่างไหม?",
    )
    
    // Serialize เป็น binary
    data, err := proto.Marshal(msg)
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("ขนาดข้อมูล: %d bytes\n", len(data))
    
    // Deserialize กลับมา
    newMsg := &pb.ChatMessage{}
    err = proto.Unmarshal(data, newMsg)
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("ข้อความ: %s\n", newMsg.Content)
}

chat.go

คำอธิบายการทำงาน:

  1. กำหนด Schema - เราสร้างไฟล์ .proto เพื่อกำหนดโครงสร้างข้อมูล เช่น ChatMessage, User, TypingIndicator
  2. Compile - ใช้ protoc compiler เพื่อสร้าง code สำหรับภาษาที่ต้องการ
   protoc --go_out=. chat.proto
  1. Serialize - แปลง object เป็น binary data ด้วย SerializeToString() หรือ Marshal()
  2. ส่งข้อมูล - ส่ง binary data ผ่าน network (socket, HTTP, gRPC)
  3. Deserialize - แปลง binary data กลับเป็น object ด้วย ParseFromString() หรือ Unmarshal()

นี่เป็นเพียงตัวอย่างง่ายๆ เพื่อให้เข้าใจการทำงานของมัน ตัว Protobuf ยังมีลูกเล่นมากกว่านี้อีกเยอะ สามารถเข้าไปดูเพิ่มเติมใน web official ของ Protobuf ได้เลย


References: