1 คะแนน โดย GN⁺ 2025-01-24 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • จุดเริ่มต้นของการออกแบบ API คือ ความแตกต่างระหว่าง RPC กับ REST และแม้ทั้งสามแนวทางจะเชื่อมโยงกับ HTTP ได้ แต่โมเดลในการสร้างการเรียกและจัดโครงสร้างไคลเอนต์แตกต่างกัน
  • REST เป็นโมเดลไฮเปอร์เท็กซ์ที่ไคลเอนต์ตาม URL ที่เซิร์ฟเวอร์ให้มา จึงแตกต่างจาก API แบบ OpenAPI ที่ไคลเอนต์ประกอบรูปแบบ URL เอง
  • OpenAPI นิยามงานด้วยเทมเพลตพาธ URL และเมธอด HTTP ใช้งานได้จริงและแพร่หลาย แต่ใกล้เคียงกับโมเดล RPC ที่แมปลงบน HTTP มากกว่า REST
  • gRPC นิยาม RPC API โดยตรงผ่าน IDL, การสร้างโค้ด, เพย์โหลดแบบไบนารี และการจัดการการเชื่อมต่อ HTTP/2 พร้อมซ่อนรายละเอียดของ HTTP
  • gRPC ต้องใช้ซอฟต์แวร์เฉพาะทั้งสองฝั่ง และมีข้อจำกัดด้านการเสริมความสามารถผ่านพร็อกซี การป้องกันการอัปเดตพร้อมกัน และการอัปเดตบางส่วน จึงเหมาะเป็นพิเศษเมื่อใช้กับ API ภายในหรือเมื่อมีเลเยอร์แปลงอย่าง Cloud Endpoints

สามโมเดลในการมอง API ที่ใช้ HTTP

  • แนวทางหลักในการใช้ HTTP เป็นเลเยอร์ส่งข้อมูลของ API แบ่งได้เป็น REST, OpenAPI และ gRPC
  • เหตุผลหนึ่งที่ API สาธารณะและ API แบบกระจายภายในจำนวนมากใช้ HTTP คือองค์กรต่าง ๆ คุ้นเคยกับปัญหาความปลอดภัยของทราฟฟิก HTTP บนพอร์ต 80 และ 443
  • ทั้งสามแนวทางเชื่อมโยงกับ HTTP ได้ แต่ต่างกันตรงสิ่งที่ใช้เป็นที่อยู่ และวิธีที่ไคลเอนต์สร้างการเรียก

REST: วิธีตาม URL โดยไม่ประกอบ URL เอง

  • ใน REST ไคลเอนต์ใช้ URL ที่เซิร์ฟเวอร์ส่งมาให้ตามเดิม และไม่เข้าใจหรือประกอบรูปแบบ URL ในฐานะส่วนหนึ่งของสเปก API
  • เบราว์เซอร์จะตามหน้าปัจจุบัน บุ๊กมาร์ก หรือ URL ที่ผู้ใช้ป้อน และทำเพียงดึงข้อมูลคำขอ HTTP จาก URL หรือแปลง URL สัมพัทธ์ให้เป็น URL แบบสมบูรณ์
  • แกนหลักของ REST API คือการใช้ ไฮเปอร์เท็กซ์/ไฮเปอร์มีเดีย ที่แสดงการอ้างอิงระหว่างรีซอร์สเป็น URL ของรีซอร์สอื่น
  • ในแนวทาง REST ตัวระบุทั้งหมดจะถูกส่งรับเป็น URL
    • POST /accountsaccount_URL
    • ส่ง account_URL ไปที่ POST /subscriptionssubscription_URL
    • GET {account_URL} → คืนทรีข้อมูลบัญชี
  • ข้อดีของ REST ใกล้เคียงกับเสถียรภาพ ความสม่ำเสมอ และความเป็นสากลของเว็บเอง และ โมเดลที่เน้นเอนทิตี ของ HTTP/REST สามารถทำให้ API เรียบง่ายและเป็นระบบมากขึ้น

OpenAPI: ใกล้เคียง RPC ที่แมปตรงกับ HTTP

  • OpenAPI นิยามเทมเพลตพาธ URL ไว้ใต้ paths และเรียกการผสมกันของพาธกับเมธอด HTTP ว่า งาน (operation)
  • พาธอย่าง /pets/{petId} กำหนดให้ไคลเอนต์ต้องรู้ค่า {petId} แล้วใส่ลงในเทมเพลต URL เพื่อสร้างคำขอ HTTP
  • ด้วยแนวทางนี้ ไคลเอนต์ต้องรู้รายละเอียดรูปแบบ URL จึงตรงข้ามกับโมเดลไฮเปอร์เท็กซ์ของ REST
  • เหตุผลที่ OpenAPI ใช้กันอย่างแพร่หลายนั้นชัดเจน
    • คล้ายกับ โมเดล RPC แบบดั้งเดิม จึงคุ้นเคยสำหรับโปรแกรมเมอร์
    • สามารถแมปแนวคิด RPC เข้ากับคำขอ HTTP ได้โดยตรง
  • สำหรับ API สาธารณะ ข้อดีสำคัญคือเข้าถึงได้จากแทบทุกภาษาและสภาพแวดล้อมด้วยเทคโนโลยี HTTP มาตรฐานเท่านั้น
  • แต่ก็ต้องออกแบบพาธ URL, เมธอด HTTP และการแมปพารามิเตอร์ ทำให้รายละเอียดที่ทั้งผู้ให้บริการและผู้ใช้ API ต้องเรียนรู้เพิ่มขึ้น

gRPC: เทคโนโลยี RPC ที่ซ่อน HTTP/2

  • gRPC ใช้ HTTP/2 เป็นเลเยอร์ส่งข้อมูล แต่ไม่เปิดเผยรายละเอียด HTTP ให้ผู้ออกแบบ API และโค้ดฝั่งไคลเอนต์·เซิร์ฟเวอร์
  • ลำดับการเรียกของไคลเอนต์ gRPC นั้นเรียบง่าย
    • ตัดสินใจว่าจะเรียกโพรซีเยอร์ใด
    • คำนวณค่าพารามิเตอร์ที่จะใช้
    • ส่งพารามิเตอร์ผ่าน stub ที่สร้างโค้ดไว้เพื่อทำการเรียก
  • gRPC นิยามโพรซีเยอร์ระยะไกลบนพื้นฐาน interface description language จึงไม่จำเป็นต้องแสดงการแมปพาธ URL, พารามิเตอร์ และเมธอด HTTP ไปพร้อมกันเหมือน OpenAPI
  • การสร้างโค้ด เฟรมเวิร์ก และไลบรารีอาจช่วยให้สร้างไลบรารีไคลเอนต์และอิมพลีเมนเทชันของเซิร์ฟเวอร์ได้ง่ายขึ้น
  • มีข้อได้เปรียบด้านประสิทธิภาพจากการใช้เพย์โหลดแบบไบนารีและการจัดการการเชื่อมต่อ HTTP/2 และแม้จะใช้เทคโนโลยีเดียวกันโดยตรงโดยไม่ใช้ gRPC ได้ แต่ต้องเรียนรู้เทคโนโลยีมากกว่า

เมื่อควรพิจารณา gRPC แทน OpenAPI

  • เมื่อออกแบบ API ด้วย OpenAPI ต้องแสดงงานและพารามิเตอร์เป็นการผสมกันของพาธ URL กับเมธอด HTTP ซึ่งมีทางเลือกมากและอาจยุ่งยาก
  • หากยังใช้โมเดลแบบ RPC ต่อไป gRPC จะช่วยลดภาระในการออกแบบ การแมปแบบกำหนดเอง ลงบน HTTP ด้วยตัวเอง
  • gRPC และ OpenAPI มีโมเดล API พื้นฐานคล้ายกัน แต่วิธีเปิดเผย HTTP ต่างกัน
    • OpenAPI เปิดเผยรายละเอียดการส่งข้อมูลของ HTTP ให้ไคลเอนต์ และให้ผู้ออกแบบควบคุมการแมป
    • gRPC ซ่อนรายละเอียด HTTP ผ่านการแมปที่กำหนดไว้ล่วงหน้าและโค้ดที่สร้างขึ้น
  • ข้อดีใหญ่ของ OpenAPI คือไคลเอนต์สามารถใช้เครื่องมือและเทคโนโลยี HTTP มาตรฐานได้โดยตรง และสำหรับผู้ออกแบบ API จำนวนมาก ข้อดีนี้ทำให้ต้นทุนการออกแบบเพิ่มเติมสมเหตุสมผล

ผสานโมเดลที่เน้นเอนทิตีเข้ากับ RPC

  • แม้จะใช้ gRPC หรือ OpenAPI หากจำกัดเมธอด RPC ให้ยึดตามเอนทิตีเป็นหลัก ก็จะได้ข้อดีบางส่วนของ REST
  • แนวทางคือไม่เริ่มจากการนิยามโพรซีเยอร์ แต่เริ่มนิยาม ประเภทรีซอร์ส ก่อน แล้วจับคู่แต่ละประเภทกับงานเอนทิตีมาตรฐาน
  • งานพื้นฐานคือ Create, Retrieve, Update, Delete, List ซึ่งมักมองได้ว่าเป็น CRUD plus List
  • หากจำเป็นสามารถมีงานเพิ่มเติมได้ แต่เมื่อแนวคิดแบบเน้นเอนทิตีผสมกับแนวคิดแบบเน้นโพรซีเยอร์ ข้อดีบางส่วนอาจลดลง
  • การจัดกลุ่มโพรซีเยอร์ตามประเภทเอนทิตียังเป็นหนึ่งในแนวคิดหลักของภาษาเชิงวัตถุด้วย

ข้อจำกัดและข้อควรระวังของ gRPC

  • gRPC ต้องใช้ ซอฟต์แวร์เฉพาะ ทั้งฝั่งไคลเอนต์และเซิร์ฟเวอร์ และต้องผนวกโค้ดที่สร้างขึ้นเข้าในกระบวนการ build ของทั้งสองฝั่ง
  • สำหรับผู้ใช้ภาษาไดนามิกอย่าง JavaScript หรือ Python ซึ่งสภาพแวดล้อมพัฒนาอาจแทบไม่มีกระบวนการ build ข้อกำหนดนี้อาจเป็นภาระ
  • Google Cloud Endpoints ทำให้เข้าถึง gRPC API ผ่าน HTTP และ JSON ได้ จึงคืนทางเลือกให้ไคลเอนต์ แต่ไม่ใช่ผู้ใช้ทุกคนจะใช้สิ่งนี้หรือสร้างฟังก์ชันเทียบเท่าได้
  • REST API ทำให้สร้างบอตที่ crawl ทั้งระบบได้ง่ายแม้ไม่มีเมทาดาทา แต่ API แบบ RPC อย่าง gRPC หรือ OpenAPI ต้องมี API และเมทาดาทาที่ต่างกันตามประเภทเอนทิตี หรือซอฟต์แวร์เฉพาะ
  • HTTP API มักเพิ่มฟังก์ชันด้านความปลอดภัย การตรวจสอบอินพุต การแมปรูปแบบข้อมูล และการแก้ไขเฮดเดอร์·บอดี้ผ่านเครื่องมือจัดการ API และพร็อกซีอย่าง Apigee Edge แต่ใน gRPC การ เสริมความสามารถผ่านพร็อกซี เช่นนี้อาจทำได้ยากกว่ามาก
  • gRPC ไม่ได้นิยามกลไกมาตรฐานในการป้องกันข้อมูลสูญหายจากการอัปเดตพร้อมกัน
    • HTTP มีเฮดเดอร์ Etag และ If-Match สำหรับเรื่องนี้
  • gRPC ไม่ได้นิยามกลไกการอัปเดตบางส่วนเช่นกัน
    • HTTP มี PATCH และสำหรับ JSON มีมาตรฐาน JSON merge patch กับ JSON patch
    • JSON merge patch เรียบง่ายกว่า แต่จัดการไม่ได้ทุกกรณี เช่น การอัปเดตอาร์เรย์
    • JSON patch จัดการได้มากกรณีกว่า แต่ใช้งานซับซ้อนกว่า

เกณฑ์การเลือก

  • หากคุณออกแบบโมเดลไฮเปอร์เท็กซ์ของ REST เป็นอยู่แล้ว หรือเต็มใจเรียนรู้ REST อาจเป็นตัวเลือกที่ดีเมื่อเป้าหมายคือเสถียรภาพ ความสม่ำเสมอ และความเป็นสากล
  • OpenAPI ทำให้สร้าง API ที่เข้าถึงได้ด้วยเทคโนโลยี HTTP มาตรฐานเท่านั้น แต่จำนวนตัวเลือกในการออกแบบเพื่อแมปแนวคิด RPC ลงบน HTTP จะเพิ่มขึ้น ทำให้การออกแบบ การใช้งาน และการเรียนรู้ยากขึ้นได้
  • หากกำลังพิจารณา API แบบ OpenAPI ก็ควรพิจารณา gRPC ร่วมด้วย โมเดล API พื้นฐานของทั้งสองแนวทางเปรียบเทียบกันได้ และ gRPC ลดความจำเป็นในการสร้างการแมป HTTP เอง
  • gRPC น่าสนใจเป็นพิเศษภายใต้เงื่อนไขต่อไปนี้
    • เมื่อใช้ผลิตภัณฑ์อย่าง Cloud Endpoints ทำให้ไคลเอนต์ไม่จำเป็นต้องนำเทคโนโลยี gRPC มาใช้เสมอไป
    • เมื่อเป็น API ภายในที่ควบคุมตัวเลือกเทคโนโลยีของเซิร์ฟเวอร์และไคลเอนต์ทั้งหมดได้
  • เมื่อนำ gRPC มาใช้แทน OpenAPI หรือ REST ควรพิจารณาว่าโอกาสในการเสริมหรือปรับแก้พฤติกรรมของ API ผ่านพร็อกซีที่ใช้เครื่องมือจัดการ API อย่าง Apigee Edge อาจถูกจำกัดกว่ามาก

1 ความคิดเห็น

 
GN⁺ 2025-01-24
ความคิดเห็นบน Hacker News
  • ถ้าย้อนเวลาได้ ผมอยากถึงขั้นกันไม่ให้ตัวเองได้เรียน gRPC ตั้งแต่แรก
    ตอนแรกก็หลงใหลในวิสัยทัศน์ของมัน แต่ผ่านไปไม่กี่ปีถึงเห็นว่ามีเรื่องปวดหัวเยอะเกินไป คำกล่าวที่ว่ามันช่วยซ่อนรายละเอียดภายในก็แทบจะเป็นเรื่องล้อเล่น และสุดท้ายต้องเท debug log ออกมาเพื่อหาสาเหตุว่าทำไม request ถึงล้มเหลว 1 ครั้งจาก 10 ครั้ง พร้อมปรับตั้งค่า timeout/retry ชื่อคลุมเครืออีก 10–20 รายการ
    ตั้งแต่ Maven plugin, deadline exceeded แปลก ๆ, load balancer ที่ไม่ชอบ HTTP/2, สถานการณ์ที่สุดท้ายต้องใช้ API มาตรฐานเพราะ firewall, เอกสารที่ขาดแคลน ไปจนถึงการพยายามให้ได้ข้อความ error ที่ใช้ได้จริงสำหรับ observability ล้วนกินเวลาไปหมด

    • ปัญหาของ gRPC ไม่ได้อยู่ที่ protocol หรือ protobuf เองเท่าไร แต่อยู่ที่อย่างน้อย toolchain ฝั่ง Java ที่แย่มาก
      developer experience ของโค้ดที่ generate ออกมาไม่ดี, client stub เป็น concrete class แบบ final ทำให้ mock ในการทดสอบได้ยาก, และการ implement server ก็ต้องสืบทอดจาก concrete class แทนที่จะเป็น interface
      method ฝั่ง server มี signature แบบ async จนทำให้พฤติกรรมที่อิง AOP อย่าง @Transactional พัง, ไม่มีการรองรับ exception, และแม้ immutable value class จะดี แต่ทั้งหมดต้องสร้างผ่าน builder
      สุดท้ายถ้าจะใช้ gRPC ใน SOA ก็ต้องเขียนโค้ด plumbing จำนวนมากเพื่อซ่อน noise ของ gRPC และให้ได้โค้ดสะอาดที่ทดสอบได้ ส่วน RPC compiler ของ Thrift ก็มีปัญหาคล้ายกันและยังมีปัญหาอื่นเพิ่มเข้ามาอีก
    • ปัญหาเหล่านั้นดูเหมือนจะเป็นปัญหาของ implementation เฉพาะเจาะจงมากกว่าตัว สเปก gRPC/protobuf เอง
      ประสบการณ์ gRPC บน .NET และ C# รุ่นใหม่ค่อนข้างดี ถึงขนาด Microsoft ก็ยุติเทคโนโลยี RPC เดิมอย่าง WCF แล้วหันมาโฟกัสที่ gRPC
    • โปรเจกต์ที่ผมเคยใช้ใหญ่ที่สุดเป็น Java และการตรวจสอบ output ของ binding ที่ protoc generate ออกมายืดยาวและพลาดง่ายกว่าการ serialize เองเสียอีก
      wire protocol ไม่ได้ type-safe และแม้จะมี type tag แต่ก็ใช้ tag เดียวกันซ้ำกับ data type หลายแบบ การเข้ารหัสจำนวนเต็มแบบ zig-zag ก็ช้า
      ในฐานะ RPC library ถือว่าแย่มาก และในสิ่งที่เคยเจอเอง มีแค่ FlatBuffers เท่านั้นที่แย่กว่า
    • เห็นพูดถึง Maven ก็น่าจะใช้ Java อยู่ แต่จากมุมของคนที่เขียน Go มาประมาณ 8 ปี ประสบการณ์กับ gRPC ค่อนข้างต่างออกไปมาก
      เลยสงสัยว่าความต่างนี้เป็นเพราะ Java หรือเพราะเทคโนโลยี gRPC เอง กันแน่
    • ผมใช้ gRPC ในสแต็ก Go+Dart มาหลายปีแล้ว แต่ไม่เคยเจอปัญหาแบบนี้เลย
      เลยสงสัยว่าเป็นปัญหาที่เฉพาะกับ Java+gRPC หรือเปล่า
  • ผมทำ API มานาน เคยใช้ทั้ง gRPC และ HTTP/REST และยังเคยเปิดซอร์สไลบรารี https://github.com/oapi-codegen/oapi-codegen สำหรับสร้างไคลเอนต์และเซิร์ฟเวอร์ Go จากสเปก OpenAPI ด้วย
    ในบทความนี้ผมเห็นด้วยยากกับวิธีที่ แยก OpenAPI ออกจาก REST OpenAPI เป็นวิธีบันทึกเอกสารพฤติกรรมของ HTTP API และสามารถอธิบายได้ทั้ง API แบบ RESTful หรือ API ที่กำหนดขึ้นเองโดยสมบูรณ์ ในแง่ที่เป็นภาษา schema สำหรับอธิบาย API ให้เครื่องมือเข้าใจได้ แนวคิดจึงคล้ายกับไฟล์ Protocol Buffer ที่กำหนดโปรโตคอล gRPC
    gRPC เป็นกลไก RPC ที่รับส่ง proto กัน โดยตอนที่ Google เปิดเผย protobuf นั้นไม่ได้เปิดเผย Stubby ซึ่งเป็นเลเยอร์ RPC ภายใน และ gRPC ก็ไม่ได้ยอดเยี่ยมเท่า Stubby แต่ถึงอย่างนั้นประสิทธิภาพการส่งข้อมูลก็ดีและขยายได้ค่อนข้างง่าย
    อย่างไรก็ตาม gRPC ไม่ใช่ ecosystem ที่แข็งแรงเท่าไลบรารี HTTP กระแสหลัก จึงมักต้องลงมือทำ middleware อย่าง logging หรือ authentication เองอยู่บ่อย ๆ โดยเฉพาะในการทำ RPC ระหว่างบริการที่ implement ด้วยภาษาต่างกัน
    ปัญหาจริง ๆ ของ gRPC ผมมองว่าอยู่ที่ไฟล์ proto เพราะไคลเอนต์ทุกตัวต้อง build ด้วยไฟล์ .proto ที่เข้ากันได้กับเซิร์ฟเวอร์ จึงไม่ใช่โปรโตคอลที่ค้นพบได้เอง HTTP API สามารถเรียกได้ด้วย curl หรือโค้ดที่เขียนเองแม้ไม่มีคำอธิบาย OpenAPI ทำให้ coupling หลวมกว่า และด้วยเหตุนี้การทำงานกับมันรวมถึงการ debug จึงง่ายกว่า

    • มีความแตกต่างระหว่างสิ่งที่บล็อกนี้เรียกว่า “OpenAPI” กับ REST ที่ถูกต้องอยู่จริง อย่างไรก็ตามในทางปฏิบัติแทบไม่มีที่ไหนสร้าง REST API ของจริง ส่วนใหญ่ใช้แนวทางแบบ OpenAPI
      REST ที่ Roy Fielding นิยามไว้ในวิทยานิพนธ์ปริญญาเอกปี 2000 คือเมื่อ GET ไปที่ root URL แล้วควรมีลิงก์ต่าง ๆ อยู่ใน response 200 OK และต้องสามารถสำรวจ resource ทั้งหมดที่ API มีให้ได้ด้วยการตามลิงก์เหล่านั้น อนุญาตให้มีโครงสร้างแบบลำดับชั้นได้ แต่ทุกอย่างต้องเข้าถึงได้จากที่ใดที่หนึ่งใน tree ของลิงก์ ซึ่งตั้งใจให้เกิด discoverability
      ในที่ทำงานจริงตลอด 20 ปีที่ผ่านมา แทบทุกแห่งใช้ POST resource_name/resource_id/sub_resource/sub_resource_id/mutation_type หรือใช้ PUT resource_name/resource_id/sub_resource/sub_resource_id ตามวิธีจัดการ idempotency ของบริษัท และไคลเอนต์ก็ประกอบ URL วิเศษขึ้นจากความรู้เชิงโครงสร้างอย่าง Swagger/OpenAPI
      ดังนั้นคนที่เคร่งในนิยามมักเรียกแนวทางในงานจริงว่า “RESTful” ไม่ใช่ “REST” เพื่อสื่อว่าไม่ได้ implement นิยาม REST ของ Fielding
    • ส่วนที่แยก OpenAPI กับ REST ก็ทำให้ผมสับสนเหมือนกัน สิ่งที่บทความเรียกว่า REST ดูใกล้กับ HATEOAS มากกว่า
      ในฐานะคนที่ดูแล API ขนาดค่อนข้างใหญ่ซึ่งมีทั้งไคลเอนต์ภายในและภายนอก ผมก็เข้าใจ workflow การ generate โค้ดจากสเปก OpenAPI ได้ยากเช่นกัน พอเติม stub ที่ generate มาแล้วปรับปรุงสเปก API ซ้ำไปเรื่อย ๆ เครื่องมือก็จะสร้าง stub ใหม่ให้อีก ต้อง merge ด้วยมือ และยิ่ง API ใหญ่ขึ้นก็ยิ่งหาการเปลี่ยนแปลงที่เกี่ยวข้องได้ยาก
      เลยทำสัตว์ประหลาดที่ใช้ go/ast และอื่น ๆ เพื่อ generate สเปก OpenAPI จากโค้ดขึ้นมา มันไม่สมบูรณ์แบบ แต่เป็นทางออก 95% ที่ใช้ได้ทั้งกับ Echo และ Gin และเมื่อจำเป็นต้องมี endpoint ใหม่ ก็สร้าง struct สำหรับ request/response กับ handler เปล่า ๆ แล้ว generate เอกสารส่งให้ frontend developer ได้อย่างรวดเร็ว
      developer ส่วนใหญ่ไม่จำเป็นต้องกังวลว่าจะอธิบาย API ด้วย OpenAPI อย่างไร และเอกสารก็ตรงกับโค้ดเสมอ
    • ปัจจุบันมี gRPC reflection สำหรับการค้นพบแล้ว: https://grpc.io/docs/guides/reflection/
    • กำลังใช้สเปก OpenAPI เพื่อสร้าง ไวยากรณ์ query คล้าย SQL ควบคู่กับ type ที่ generate มาอยู่ด้วย วิธีนี้ทำให้จัดการ API ของ third party ใด ๆ ได้ด้วยความรู้สึกเดียวกัน
      Apipe.new(GitHun) |> from("search/repositories") |> eq(:language, "elixir") |> order_by(:updated) |> limit(1) |> execute()
      ไม่จำเป็นต้องรู้ฟังก์ชัน gRPC ที่ใช้ได้หรือจุดเฉพาะแบบ RESTful ของ API third party และยังคงเข้าถึงเอกสารในตัวกับ type ได้
      https://github.com/cpursley/apipe
      กำลังพิจารณาเลเยอร์ adapter ของ TypeScript เพื่อให้ใส่ในโปรเจกต์ JS/TS ได้เหมือน Supabase
      const { data, error } = await apipe.from('search/repositories').eq('language', 'elixir').order_by('updated').limit(1)
      การเรียกนี้สามารถส่งผ่าน proxy ของ Elixir เพื่อให้รับงานหนัก ๆ อย่างการประมวลผลแบบ asynchronous หรือ rate limiting ได้
    • คำกล่าวว่า gRPC ไม่ใช่โปรโตคอลที่ค้นพบได้เองนั้นไม่ได้ถูกต้องทั้งหมด
      สามารถสร้างคำอธิบาย OpenAPI จาก JSON serialization ของ Protobuf แล้วให้บริการผ่าน Swagger ได้ และตัว gRPC เองก็มี reflection ในตัวรวมถึง utility grpcurl ที่ใช้สิ่งนี้
  • จากมุมมองของคนที่เคยทำงานในบริษัทกลุ่ม FAANG บางแห่ง Thrift/gRPC มีประโยชน์มากจริง ๆ สำหรับการ routing ระหว่างบริการภายใน
    แต่ความซับซ้อนส่วนใหญ่ของมันถูกจัดการให้โดยทีมที่สร้างไลบรารี, ชั้น service discovery, routing ฯลฯ การใช้โปรโตคอล RPC ทำให้ทำสิ่งเหล่านี้ได้ในสเกลและความเร็วที่บริการ JSON/REST ทั่วไปทำได้ยาก
    ผมไม่เคยเห็น REST API ที่ไม่ปล่อยให้ verb หลุดออกมาเลย และถ้าต้องสร้าง service mesh ฝั่งแบ็กเอนด์ หรือเชื่อมบริการโลคัลสองตัวเข้าด้วยกันผ่าน network stream ผมจะเลือก gRPC เสมอ
    แต่ถ้าเป็นการเปิดให้ลูกค้าหรือเว็บใช้งาน ผมจะไม่ใช้ gRPC เด็ดขาด RPC ทรงพลังเพราะมันตรึงการตัดสินใจไว้หลายอย่างและบังคับให้ใช้ “วิธีเดียว” ในทางกลับกัน ถ้าคลients ที่มีเทคสแต็กหลากหลายต้องใช้บริการ REST ดีกว่ามาก

    • สำหรับ API สาธารณะคงไม่ทำ แต่ใน API ส่วนตัว ผมก็แค่ทำแบบ POST /api/doThingy แล้วส่ง body เป็น JSON
      มันเป็น RPC แบบง่าย ๆ ที่ใครก็ตามที่มี HTTP client พื้นฐานที่สุดก็เข้าร่วมได้ และทำงานได้ดีบนทุก OS และเบราว์เซอร์ ไม่ต้องมานั่งสู้กันว่าจะใส่ไว้ใน path ของ URL, query parameter หรือ body
      ถ้าใช้สายเซิร์ฟเวอร์อย่าง Buf หรือ Connect ที่พยายามทำให้ลำบากน้อยลง gRPC ก็ยอมรับ JSON ผ่าน HTTP ได้อย่างเต็มใจ
    • สงสัยว่าแอปพลิเคชัน client/server ที่ไม่ใช่เว็บเป็นอย่างไร
      ผมนึกถึงกรณีอย่างเกมออนไลน์หรือ MMO ที่ต้องการการสื่อสารแบบเรียลไทม์มากกว่า REST มาก ๆ แต่ก็ไม่ค่อยแน่ใจว่าสมัยนี้เขาเอาอะไรบางอย่างไปวางบนการเชื่อมต่อ socket กันหรือเปล่า
    • ถ้า Thrift/gRPC เป็นพรในงาน routing บริการภายใน ก็อยากรู้ว่า เมื่อเทียบกับอะไร ถึงเป็นแบบนั้น
      อยากรู้ด้วยว่าเคยลองอย่างอื่นอะไรมาบ้าง
    • สงสัยว่า “verb หลุดออกมา” หมายความว่าอะไร
  • ถ้าไม่ได้ทำ bidirectional streaming ผมมองว่า gRPC โดยรวมแล้วเสียเวลาเปล่า
    มีทั้งนรกของ transitive dependency ตอน runtime, นรกของ toolchain และดูเหมือนว่าทีมที่ดูแลแต่ละ implementation ภายใน Google เองก็ยังตกลงกันในเชิงปรัชญาไม่ได้ว่าฟังก์ชันพื้นฐานควรทำงานอย่างไร
    ลองเปิด gRPC API ให้ทีมที่ไม่ได้ใช้ภาษาของคุณ โดยเฉพาะถ้าไม่ใช่ Go/Python/Java หรือแม้แต่ใช้เวอร์ชันเก่า, หรือลอง integrate กับผลิตภัณฑ์สำเร็จรูปเชิงพาณิชย์, หรือลองเปิดให้เบราว์เซอร์ใช้ดู ทั้งหมดจะต้องมี ชั้นกลาง เข้ามา

    • เคยใช้ gRPC ในหลายบริษัทและหลายทีม ขนาดวิศวกรของแต่ละบริษัทประมาณ 100~500 คน แต่ไม่เจอปัญหา dependency หรือ toolchain
      gRPC โดยรวมค่อนข้างราบรื่น
    • ผมคิดว่าไม่ควรเปิดให้เบราว์เซอร์ใช้โดยตรง นั่นไม่ใช่พื้นที่ที่ gRPC ทำได้ดี และทำชั้นปรับแต่งเพื่อแปลงเป็น JSON จะดีกว่า
      การใช้ REST เพื่อสื่อสารระหว่างบริการฝั่งแบ็กเอนด์ก็ไม่ค่อยมีความหมายหากมีข้อกำหนดด้านประสิทธิภาพ และถ้าไม่ใช่ call ที่ดึงข้อมูลเล็ก ๆ เป็นครั้งคราว ก็แทบไม่มีเหตุผลที่จะใช้โปรโตคอล/API ที่มนุษย์อ่านได้
    • จำได้ว่าเคยพยายามเปิด gRPC API ให้เบราว์เซอร์ แล้วถูกซักไซ้ว่าไม่ได้ทำอินเทอร์เฟซให้ “เหมือน JSON”
      เมื่อส่งคืน subtype ของ oneof ที่เป็นชนิดที่ตอนนี้ไม่มีฟิลด์ ผลการแปลงอัตโนมัติออกมาเป็น { "id": "id", "sub_type_two": { } }
      ในเชิงฟังก์ชันมันทำงานได้ และถ้ามีฟิลด์เพิ่มในภายหลัง โค้ดนั้นก็ยังทำงานต่อได้ แต่ในโลกเว็บ การใช้ออบเจ็กต์ว่างเพื่อแสดงชนิดของ response มันแปลก และตอนเขียน protobuf ปัญหาแบบนี้อาจมองไม่ค่อยเห็น
    • bidirectional streaming โดยทั่วไปเป็นแนวคิดที่ไม่ดีสำหรับสิ่งที่ตั้งใจจะรัน “อย่างมีสเกล”
    • Protobuf ไม่เหมาะกับ streaming
      เมื่อเทียบกับโปรโตคอลไบนารีแทบทุกแบบที่จินตนาการได้ มันใกล้เคียงกับ กึ่งต่อต้าน streaming
  • ประสบการณ์เดียวที่เคยใช้ gRPC ในบริษัทคือโปรเจกต์ที่นักพัฒนาซีเนียร์อีกคนผลักดันโดยบอกว่า “ต้องการประสิทธิภาพ”
    สุดท้ายก็ต้องทำ JSON API ด้วย เพราะฟรอนต์เอนด์ต้อง consume ได้ และนอกจากนักพัฒนาคนนั้นก็ไม่มีใครมีประสบการณ์ gRPC เลย เอาเข้าจริงนักพัฒนาคนนั้นเองก็ไม่ได้ไปไกลกว่า quick start guide ของ gRPC Python และไม่ได้ช่วยแก้บั๊กด้วย
    โปรเจกต์เละเทะด้วยเหตุผลมากมาย และไม่เคยไปถึงสเกลที่พอจะ justify การใช้ gRPC ได้เลย
    ถึงอย่างนั้น gRPC ที่ผมลองใช้เองนิดหน่อยก็ชอบนะ และรู้สึกว่าต้องใช้ทั้งงานและการคิดไตร่ตรองมากกว่านี้มาก นั่นอาจเป็นเพราะผมเคยทำ JSON API มามากกว่ามากก็ได้

    • นั่นดูเหมือนเป็นคำวิจารณ์ต่อนักพัฒนา “ซีเนียร์” ที่ก่อนจะ adopt ยังไม่รู้ด้วยซ้ำว่า มันไม่เข้ากับเบราว์เซอร์ มากกว่าจะเป็นตัว gRPC เอง
  • กำลังใช้ ConnectRPC https://connectrpc.com/ อย่างสนุก
    มันแก้ส่วนที่มีปัญหาของ gRPC ได้เยอะ และหวังว่าเมื่อ Safari ยอมรับ WebTransport แล้ว ConnectRPC จะพัฒนา streaming ที่ดีกว่านี้ได้
    ตอนแรกคิดว่า https://buf.build เยอะเกินจำเป็น แต่ความสามารถในการดึงไฟล์ proto ของ third-party มาใช้ได้โดยไม่ต้องดาวน์โหลดทีละไฟล์คือจุดตัดสินใจ
    deps:
    - buf.build/landeed/protopatch
    - buf.build/googleapis/googleapis
    การสร้าง SDK อัตโนมัติก็สำคัญ เมื่อก่อนกำลังจะชมว่ามันสร้าง SDK อัตโนมัติสำหรับประมาณ 9 ภาษา แต่เพิ่งอัปเดตในช่วงหนึ่งสองวันที่ผ่านมา ตอนนี้เห็นว่าเป็น 16 ภาษา พร้อม OpenAPI และฟีเจอร์ใหม่อื่น ๆ แล้ว
    ผมเองก็เคยหวั่นไหวกับคำสัญญาลวงของ gRPC streaming และเอกสารนี้ตรงกับประสบการณ์ของผมเป๊ะ: https://connectrpc.com/docs/go/streaming/

    • ผมทำ wrapper ที่ใช้ WebSocket เล็ก ๆ สำหรับ ConnectRPC streaming เพื่อให้ทำงานบน ReactNative ได้
      ด้วยเหตุนี้จึงใช้ bidirectional streaming บนเบราว์เซอร์ได้ด้วย
    • ถึงอย่างไรก็ยังใช้ Protocol Buffers อยู่ และปัญหาหลายอย่างที่ผมเจอกับ gRPC ก็มาจากตรงนั้นเอง
    • สงสัยว่ามีข่าวล่าสุดเกี่ยวกับการรองรับ WebTransport ของ Safari หรือไม่
  • รู้สึกเหมือน Google ทำสงครามจิตวิทยากับทั้งวงการจนทำให้ทุกคนใช้ gRPC สำหรับการสื่อสารระหว่างบริการภายใน
    ประสบการณ์นักพัฒนาของ gRPC แย่กว่า REST ค่อนข้างมาก
    คุณไม่สามารถส่งคำสั่งง่าย ๆ เพียงคำสั่งเดียวให้ใครสักคนเพื่อเรียก endpoint ได้ และต้องใช้เครื่องมือเสริมที่ไม่ได้เป็นมาตรฐาน แถมโค้ดฝั่งไคลเอนต์ที่สร้างออกมายังเป็นก้อนโค้ดน่าเกลียดแบบที่แทบไม่ค่อยเห็นในภาษาใด ๆ

    • จากมุมมองแบ็กเอนด์ ผมไม่เห็นด้วยอย่างแรงกับคำกล่าวที่ว่าประสบการณ์นักพัฒนาของ gRPC แย่กว่า REST
      แค่มีการเปลี่ยนแปลงโปรโตคอลหนึ่งครั้ง ก็สามารถรู้แบบ static ได้ว่าผู้บริโภค downstream รายใดต้องอัปเดตและ redeploy ทำให้งานที่อาจกินเวลาหลายสัปดาห์ลดเหลือการเปลี่ยนแปลงภายในหนึ่งชั่วโมงได้
      ยังรู้ด้วยว่าข้อความที่รับเข้าและส่งออกถูกตรวจสอบความถูกต้องทันที และสามารถจัดเก็บไว้ด้วยต้นทุนต่ำเพื่อกู้คืนในภายหลังได้
      จาก proto เราได้เอกสาร API ที่อ่านง่ายมาก และไม่ถูกทำให้คลุมเครือด้วยโค้ดหรือ business logic นอกจากนี้ยังมี version management และความหมายของการเลิกใช้ที่ฝังมาในตัว และถ้าไม่นับ map ก็รองรับโครงสร้างข้อมูลที่สมบูรณ์กว่า
      เมื่อเทียบกันแล้ว JSON ดูบวมและล้าสมัยในฝั่งแบ็กเอนด์
    • gRPC เป็นมาตรฐานในแง่สำคัญ ๆ
      เมื่อเขียน data type และ function signature ไว้ ก็จะได้สิ่งที่เรียกได้เหมือนฟังก์ชันจริง และสามารถโฟกัสกับ business logic แทน boilerplate สำหรับ serialization/deserialization
      Thrift ก็เช่นกัน ดีกว่าวิธีทำเองทั้งหมดมาก และผมมองว่า GraphQL ดียิ่งกว่า
    • เคยถูกบังคับให้ใช้ในหลายบริษัท แต่ 99% เป็นการลงทุนในหนี้ทางเทคนิคที่ไม่จำเป็น
      แม้แต่ใน Go การทำความเข้าใจเรื่องการ regenerate และการจัดการเวอร์ชัน proto ที่แชร์กันก็ยุ่งยาก และยิ่งเพิ่มภาษาเข้ามาทีละภาษาก็ยิ่งแย่ลง
      ถึงอย่างนั้นดูเหมือนสตาร์ทอัพทุกแห่งจะคิดว่าตัวเองต้องมี microservice 100 ตัวกับ gRPC
  • ประโยคที่ว่า “ถ้า API เป็น REST API ไคลเอนต์ไม่จำเป็นต้องเข้าใจรูปแบบ URL และรูปแบบนั้นไม่ใช่ส่วนหนึ่งของสเปก API ที่ให้แก่ไคลเอนต์” สอดคล้องกับนิยาม REST ของ Roy Fielding
    Fielding เขียนไว้ว่า REST API ควรเข้าใช้งานได้โดยไม่ต้องมีความรู้ล่วงหน้านอกจาก URI เริ่มต้นและชุด media type ที่เป็นมาตรฐาน และหลังจากนั้นการเปลี่ยนสถานะของแอปพลิเคชันทั้งหมดควรเกิดจากการที่ไคลเอนต์เลือกตัวเลือกที่เซิร์ฟเวอร์จัดให้
    https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypert...
    เป็นเรื่องที่ถูกพูดถึงกันมามากแล้ว แต่ก็ยังน่าสนใจที่ในระบบ RESTful จริง ๆ “สเปก API” ที่ให้แก่ไคลเอนต์ควรมีเพียง URI/URL จุดเข้าเริ่มต้นเท่านั้น

    • แนวคิด REST ที่อธิบายตัวเองได้นี้ ตอนนี้รู้จักกันดีกว่าในชื่อ HATEOAS
      โดยส่วนตัวผมมองว่ามันบวมและไม่ได้แก้ปัญหาจริง
      https://en.m.wikipedia.org/wiki/HATEOAS
    • สงสัยว่าจะเขียน API client สำหรับ REST API ที่เปิดเผยแค่จุดเข้าเริ่มต้นได้อย่างไร
      โดยเฉพาะไม่รู้ว่าไคลเอนต์ควรค้นพบ resource ที่จัดการได้หรือโมเดล request/response อย่างไร
    • ผมไม่เห็นด้วยเต็มที่ว่ ในระบบ RESTful จริง ๆ สเปก API ที่ให้แก่ไคลเอนต์ควรมีเพียง URI/URL จุดเข้าเริ่มต้นเท่านั้น
      การตั้งค่าอาจเป็นแบบนั้นได้ แต่สเปก API ควรมีมากกว่า URL มาก และต้องอธิบาย media type ที่ระบบใช้อย่างละเอียด กล่าวคือส่วนใหญ่ต้องอธิบายเนื้อหา HTTP request/response body
      ในลิงก์ก็ระบุว่า “REST API ควรทุ่มความพยายามในการอธิบายแทบทั้งหมดไปกับนิยาม media type ที่ใช้แทน resource และขับเคลื่อนสถานะของแอปพลิเคชัน”
      สุดท้ายแล้วมันไม่ใช่แค่ส่งคืน application/json แต่เป็นการส่งคืนบางอย่างแบบ +json เฉพาะ และส่วนใหญ่มีข้อมูลธุรกิจที่แอปพลิเคชันต้องเข้าใจ ไม่ใช่ JSON ทั่วไป
      ในการถกเถียงทั่วไปมักโฟกัสแค่ URL เริ่มต้น และงานส่วนใหญ่ที่ Fielding บอกว่า “จงอธิบาย media type” ถูกละทิ้งไป ดังนั้นจึงเป็นธรรมดาที่คนได้ยินว่า “มี URL เดียวก็พอ” แล้วจะถามว่า “แล้วสเปกที่เหลืออยู่ไหน?”
    • ทั้งสองฝ่ายเห็นด้วยกับเรื่องเดียวกัน ที่นี่ “รูปแบบ URL” หมายถึงรูปแบบของ URL ตามตัวอักษร ไม่ใช่รูปแบบของ resource
      ตอนแรกผมกดเข้าไปอ่านเพราะนึกว่าเป็นบล็อกเกอร์อีกคนที่ไม่เข้าใจ REST แต่ดูเหมือนผู้เขียนอย่างน้อยก็เข้าใจแนวคิดพื้นฐาน
      ผมก็ชอบ gRPC และในโปรเจกต์เชิงพาณิชย์มันก็น่าสนใจพอสมควร แต่ถ้าเป็นโปรเจกต์ส่วนตัวหรือเชิงอุดมคติ ผมคิดว่า REST ดีกว่า
    • นี่เป็นตัวอย่างคลาสสิกของไอเดียดี ๆ ที่กลายเป็นกระแส แล้วผู้คนก็เข้าใจไอเดียนั้นผิดแต่ยังคงเผยแพร่ต่อไป
  • ไม่ชอบการใช้ gRPC ภายในดาต้าเซ็นเตอร์
    มักเลือกใช้ด้วยเหตุผลด้านประสิทธิภาพ แต่ gRPC เรียกได้ยากว่ามีประสิทธิภาพสูง และคุณภาพของไคลเอนต์สาธารณะก็ต่ำมาก โดยเฉพาะนอก implementation หลักของ C++/Java เช่น implementation ของ Node.js
    ไม่ได้คัดค้านการใช้ protobuf เป็นสเปก API แต่ควรใช้ร่วมกับ framing protocol บน TCP ได้ อย่างไรก็ตาม ใน RPC รูปแบบนั้นยังไม่มีตัวเลือกที่โดดเด่นชัดเจน
    สำหรับ API บนเว็บ ผมชอบ payload ที่อ่านได้มากกว่า แต่โดยทั่วไปพอใช้ JSON ความเฉพาะเจาะจงของ type ก็จะหลวมลง ทำให้เกิดปัญหา interoperability ระหว่างภาษาแบ็กเอนด์ โดยเฉพาะใน Node.js ที่ JSON.parse ถูกใช้เหมือนเป็น implementation สำหรับ mapping schema
    ถ้าจะทำให้ถูกต้อง ต้องสร้าง encoder และ decoder จาก schema อย่างชัดเจน และเมื่อทำแบบนั้น ข้อดีของการใช้ JSON ในบริบท JS ก็ลดลงไปพอสมควร

    • ถ้ากังวลเรื่องประสิทธิภาพจนถึงขั้นพิจารณา gRPC ก็สงสัยว่าทำไมถึงยังโอเคกับการวาง Node.js ไว้ใกล้ ๆ stack
    • เห็นด้วย และสำหรับปัญหา schema ใน JS นั้น Zod ช่วยได้มาก
      กำลังจับตาโปรเจกต์ TypeSpec ของ Microsoft อยู่ด้วย: typespec.io
    • ข้อดีหลักของ proto คือ interoperability ระหว่างหลายภาษา
      ถ้าเป็นเทคโนโลยี stack ภาษาเดียว ความสำคัญก็ลดลง และถ้าใช้ภาษานอกเหนือจากภาษาหลัก ๆ ของ Google ประสบการณ์ก็น่าจะไม่ดีเท่านั้น
    • ในปี 2023 มีการนำเสนอเกี่ยวกับ Homa ซึ่งเป็นโปรโตคอลที่ไม่อิง TCP สำหรับ RPC ในดาต้าเซ็นเตอร์: https://youtu.be/xQQT8YUvWg8?si=g3u5TogBe0_QpPpj
  • gRPC ทำให้คนส่วนใหญ่ที่อยู่นอก Google รู้สึกว่าเข้าถึงยากโดยไม่จำเป็น
    ไคลเอนต์ gRPC JS หนักโดยไม่จำเป็นและค่อนข้างไม่โปร่งใส แนวคิดดี แต่เมื่อเทียบกับคนที่คุ้นกับ “ความเรียบง่าย” ของ REST แล้ว การนำไปใช้ยังน่าผิดหวัง

    • ที่รอยต่อระหว่างฟรอนต์เอนด์/แบ็กเอนด์ มีการปะทะกันระหว่างฝ่าย REST/JSON กับฝ่าย RPC/protobuf/gRPC
      RPC ดูแลรักษาง่ายกว่าในเชิงความหมาย เพราะไม่ต้องฝืนยัดคาร์ดินาลิตีหรือความสัมพันธ์ของโมเดลข้อมูลให้เข้ากับแพตเทิร์นเชิงกำหนดแบบเดียว ในโลกที่ API เปลี่ยนเร็ว การทำให้เอนทิตีแบบ RESTful สวยงามลงตัวเป็นเรื่องยาก และสำหรับทีมใหญ่กับความต้องการ/ความเป็นเจ้าของที่เปลี่ยนไป การออกแบบแบบเน้นบริการจะดีกว่า
      ฝั่งฟรอนต์เอนด์ไม่ได้ดูแลระบบแบ็กเอนด์ พวกเขาต้องการ API ที่เข้าใจง่าย และต้องการเอนทิตีที่สามารถ abstractions ด้วย REST ได้ พวกเขาคือผู้ได้ประโยชน์ปลายทางของการออกแบบแบบนั้น
      ความพยายามที่ต้องใช้กับ REST มีความหมายสำหรับบริษัทที่ขาย API และมีนักพัฒนาภายนอกเป็นลูกค้าหลัก
      สำหรับการพัฒนาแบ็กเอนด์ protobuf และการเข้ารหัสบนสายแบบไบนารีทำได้ง่ายกว่า สามารถนิยาม API แล้วแชร์ระหว่างบริการด้วยวิธีแบบ static type ได้ และยังลดเวลา encode/decode ข้อความด้วย JSON ไม่ได้มีความหมายเชิง semantic ไม่ได้มี type และมี overhead สูง
      ในทางกลับกัน ฟรอนต์เอนด์จัดการข้อความและ JSON ได้แบบ native ไม่อยากดาวน์โหลดนิยาม protobuf หรือ扱กับข้อมูลไบนารีเหมือนพลเมืองชั้นสอง และมันก็ไม่เข้ากับเครื่องมืออย่างสะอาดนัก
      gRPC มีเรื่อง routing, retry, side channel, streaming และ semantics ของการเลิกใช้โปรโตคอลอยู่ดี แต่แทบไม่ปรากฏให้ฟรอนต์เอนด์เห็น ทั้งหมดนี้ทำมาเพื่อผู้บริโภคฝั่งแบ็กเอนด์
      สุดท้ายแล้วมันคือ ช่องว่างของเครื่องมือระหว่างฟรอนต์เอนด์/แบ็กเอนด์ 100% และเป็นความไม่สอดคล้องกันของอินเทอร์เฟซกับ usability
    • REST คล้ายกับ HTML
      โดยพื้นฐานแล้วดู source ได้ คนอ่านได้ และตรวจสอบง่าย
      gRPC มีไว้ให้เครื่องคุยกันอย่างมีประสิทธิภาพ และถ้ามีมนุษย์เข้ามาเกี่ยว ไม่ว่าจะเขียนโค้ดหรือตรวจ request/response ก็จะไม่สะดวกอยู่บ้าง
      ความต่างด้าน usability แบบนี้เข้าใจได้ เพราะบริบทและเป้าหมายต่างกัน
    • implementation อย่างเป็นทางการของ gRPC JavaScript ค่อนข้างไม่ดีนัก
      ในมุมมองของผม implementation ของฝั่ง buf.build ดีกว่า
      https://buf.build/blog/protobuf-es-the-protocol-buffers-type...
    • gRPC เป็นไอเดียที่ดี แต่หนักขึ้นเพราะแนวทางแก้ปัญหาแบบ ปัญหาสไตล์ Google ที่ผมไม่ได้มี
      ดูเหมือนหลายคนเลือกมันเพราะต้องการโปรโตคอลบางอย่างอย่าง binary RPC ที่มี contract แต่ยิ่งห่างจาก GoLang ก็ยิ่งแย่ลง
    • มีกรณีใช้งานที่ gRPC โดดเด่นอยู่ Streaming เป็นหนึ่งในนั้น โดยสามารถส่งสตรีมข้อความภายใน “การเชื่อมต่อ” เดียวได้อย่างโปร่งใส
      ถ้าเป็นบริการ CRUD ธรรมดา REST ก็เพียงพอแล้ว