25 คะแนน โดย disjukr 2022-04-06 | 8 ความคิดเห็น | แชร์ทาง WhatsApp

ที่ Riiid ซึ่งให้บริการ Santa TOEIC มีการใช้งาน gRPC/Protobuf อย่างเข้มข้นมาก
ไม่นานหลังจากที่ผมเข้าทำงานที่ Riiid ก็ได้รับแจ้งว่าในอนาคต API ทั้งหมดที่ทีมแบ็กเอนด์ส่งมอบให้ฝั่งฟรอนต์เอนด์ (มือถือ/เว็บ) จะถูกรวมให้เป็น gRPC ทั้งหมด

หากต้องการใช้สแตก gRPC/Protobuf บนเว็บฟรอนต์เอนด์ เดิมทีมีวิธีอย่างการต่อปลั๊กอิน JS/TS เข้ากับ protoc หรือใช้ Protobuf.js

ปลั๊กอิน JS อย่างเป็นทางการของ protoc มีปัญหาตรงที่สร้างโค้ดในสไตล์ที่เก่ามาก ส่วนปลั๊กอินใน ecosystem เองก็ยังไม่สามารถตอบโจทย์ความต้องการของเราได้ทั้งหมด อีกทั้งยังมีความไม่สะดวกจากการต้องพึ่งพา native binary (protoc) ด้วย (ทุกวันนี้ยังมีปัญหาว่าติดตั้ง protoc บนอุปกรณ์ M1 ได้ยากด้วย)

เราใช้ Protobuf.js สร้างผลิตภัณฑ์หลายตัวมาโดยตลอด แต่เมื่อบริษัทใช้ Protobuf กับทุกอินเทอร์เฟซที่ใช้สื่อสารข้ามแพลตฟอร์มในทุกผลิตภัณฑ์ที่พัฒนาขึ้น ก็พบว่า Protobuf.js ยังไม่ mature ในระดับที่เราต้องการ
มีปัญหาหลายอย่าง เช่น ถ้าชื่อ message เหมือนกัน บางครั้งจะเข้าใจผิดว่าเป็น message ที่อยู่ใน namespace อื่น หรือถ้ามีการประกาศ message ต่อจาก enum ใน global namespace ก็จะไม่สร้างโค้ดประเภท message ให้ หรือ type definition ของ TypeScript ที่สร้างออกมาก็ไม่ตรงกับพฤติกรรมของ JS ที่ถูกสร้างขึ้น เป็นต้น

ระหว่างกระบวนการนี้ เพื่อสร้างระบบที่คัดเฉพาะ protobuf schema ที่จำเป็นต่อแต่ละผลิตภัณฑ์มาทำบิลด์ เราจึงสร้างตัวจัดการแพ็กเกจ protobuf ชื่อ pollapo ขึ้นมา
(ตอนนั้นมีตัวจัดการ dependency ของ protobuf อื่นอยู่บ้าง แต่มีทั้งปัญหา bug หรือไม่รองรับ nested dependency เป็นต้น นอกจากนี้ฟังก์ชันจัดการแพ็กเกจของ buf ในเวลานั้นยังมีเพียงบล็อกโพสต์ที่บอกว่ากำลังพัฒนาอยู่ และกว่าจะถึงตอนที่เราสร้าง pollapo และทำ internal migration เสร็จ ก็ยังไม่เสร็จสมบูรณ์)

ด้วย pollapo เราลดจำนวน schema ที่ต้องบิลด์ต่อผลิตภัณฑ์ลงได้มาก และลด bug ที่เกิดจากชื่อ message ซ้ำกันได้ แต่ถึงอย่างนั้นก็ยังมี bug และปัญหาในการบิลด์อยู่ เราจึงสร้างคอมไพเลอร์ protobuf to typescript ขึ้นมาเองเพื่อแก้ปัญหาเหล่านี้

ปัจจุบัน Santa TOEIC ได้ถอด protobuf.js ออกทั้งหมดและเปลี่ยนมาใช้ pbkit เรียบร้อยแล้ว


แอปที่พัฒนาที่ Riiid รวมถึง Santa TOEIC ใช้งานเว็บวิวอย่างมาก
เว็บวิวต้องสื่อสารกับ native เพื่อดึงข้อมูลอุปกรณ์/ผู้ใช้ หรือข้อมูลคอนเทนต์ที่กำลังแสดงอยู่ และอินเทอร์เฟซในส่วนนี้ก็กำหนดด้วย Protobuf service schema เช่นกัน

pbkit มีอินเทอร์เฟซที่ทำให้ตอนสร้าง service code สามารถสลับ network layer จาก gRPC ไปเป็นโปรโตคอลอื่นได้
วิศวกรเว็บฟรอนต์เอนด์ที่ใช้ pbkit compiler จึงไม่จำเป็นต้องรู้ว่าเวลาสื่อสารกับ mobile native นั้นกำลังส่งคำขอผ่าน gRPC หรือผ่าน App Bridge protocol ที่ตกลงไว้กับวิศวกรมือถือ

และเพราะเราได้พัฒนาส่วนขยาย Chrome ขึ้นมาเองด้วย จึงสามารถตรวจสอบเนื้อหาการสื่อสารกับมือถือได้อย่างสะดวกในแท็บ pbkit ของ Chrome DevTools ราวกับดูที่แท็บ Network

เนื่องจากเราสร้าง protobuf schema compiler ขึ้นมาเอง จึงคิดว่าน่าจะทำฟีเจอร์อย่าง Go to Definition ในตัวแก้ไขโค้ดได้อย่างรวดเร็ว เลยทำส่วนขยาย VSCode ขึ้นมาด้วย
ก่อนหน้านี้ส่วนขยาย protobuf สำหรับ VSCode ที่มีอยู่มักให้ความสามารถแค่ syntax highlighting แต่ pbkit vscode extension มีฟีเจอร์ Go to Definition ที่ทำงานได้อย่างถูกต้องรวมอยู่ด้วย

ต่อจากนี้เรามีแผนจะพัฒนาการรองรับภาษาอื่นอย่าง swift/kotlin/python, รองรับ use case ฝั่งเซิร์ฟเวอร์, เครื่องมือสร้างเอกสาร, เครื่องมือ linting/formatting เป็นต้น
และเราก็กำลังมองหาวิศวกรที่จะมาร่วมพัฒนาเครื่องมือเหล่านี้ด้วย: https://riiid.com/ko/career/dx-software-engineer

ขอฝากไว้ในความสนใจด้วย

คลังเก็บ pbkit: https://github.com/pbkit/pbkit
ส่วนขยาย vscode: https://marketplace.visualstudio.com/items?itemName=pbkit.vscode-pbkit
ส่วนขยาย Chrome: https://chrome.google.com/webstore/detail/pbkit-devtools/fjacmiijeihblfhobghceofniolonhca

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

 
sixmen 2022-04-06

ที่บริษัทของพวกเรา เมื่อหลายปีก่อนตอนชั่งใจระหว่าง gRPC ก็ได้เลือก Thrift ไปครับ/ค่ะ Thrift เองก็มี JS generator ที่ยังไม่สมบูรณ์ เลยต้องแก้ไขกันเอง และก็ได้ตระหนักว่านี่เป็นงานที่ไม่ควรทำเลย เลยแอบคิดว่าน่าจะเลือก gRPC ตั้งแต่แรกหรือเปล่า แต่ดูเหมือนว่าทางนั้นเองก็ใช่ว่าสถานการณ์จะดีนัก

หลังจากนั้นพวกเราเลือก GraphQL และส่วนตัวผม/ฉันก็พอใจกับมันอยู่ครับ/ค่ะ บางครั้งก็แอบกังวลเรื่อง communication overhead แต่ก็คงใช้โปรโตคอลแบบไบนารีไม่ไหวจริง ๆ

 
cometkim 2022-04-06

ที่ Karrot Market ใช้งานกันได้ดีมากเลยครับ!! ( _ _ )

กำลังพยายามเอาไปใช้ให้คุ้มสำหรับ API mesh ภายในอยู่ครับ 555

 
kbumsik 2022-04-06

ว่าแต่ถ้าในบริษัทใช้ถึงขั้น production กันแล้ว ก็น่าจะเลิกใช้เวอร์ชันที่ดูเป็น pre-alpha อย่าง v0.0.44 ได้แล้วนะครับ

ดูแค่เลขเวอร์ชันอย่างเดียวก็น่าจะมีคนที่ไม่กล้าใช้เหมือนกัน T_T

 
winterjung 2022-04-06

ว้าว คุณสร้างคอมไพเลอร์ขึ้นมาเองเลยสินะ สุดยอดมาก! (ผมสงสัยอยู่เหมือนกันว่าโค้ด golang ถูกสร้างออกมาอย่างไร แต่ตอนนี้ดูเหมือนว่าจะรองรับแค่ deno กับ node.js เท่านั้น) ปกติผมมักใช้ protoc หรือ buf ร่วมกับ ts-proto เลยอยากรู้ว่าระหว่างโค้ด ts ที่ถูก generate ออกมากับของ ts-proto นั้นมีความแตกต่างกันอย่างไรบ้างครับ

 
bichi 2022-04-06

เหมือนจะรู้สึกว่าอ้อมไปอ้อมมานะ https://github.com/trpc/trpc

 
danchu 2022-04-06

คุณ bichi / ถ้า API ของเซิร์ฟเวอร์ถูกให้บริการด้วยโปรโตคอล gRPC กรณีแบบนี้ tRPC ก็คงไม่ได้มีไว้เพื่อรองรับสิ่งนั้นใช่ไหมครับ~?

 
disjukr 2022-04-06

ผมเห็นด้วยว่าการใช้สแตก gRPC/Protobuf ไม่ได้เป็นทางเลือกที่เหมาะที่สุด (ไม่ใช่ว่าผมอยากใช้เอง แต่ใช้เพราะข้อจำกัดของบริษัท)
อย่างไรก็ตาม trpc กำหนดอินเทอร์เฟซด้วย zod จึงน่าจะเหมาะอย่างยิ่งเมื่อใช้ TypeScript บนทุกแพลตฟอร์ม
แต่สำหรับสภาพแวดล้อมของเราที่เขียนเซิร์ฟเวอร์ด้วย kotlin ก็ดูเหมือนว่าจะใช้งานได้ยาก และในกรณีที่ต้องสื่อสารกับโมบายเนทีฟ (swift, kotlin) ก็ดูไม่ค่อยเหมาะเช่นกัน

 
xguru 2022-04-06

ว้าว มีถึงส่วนขยาย VS/Chrome ในโค้ดด้วย.. เจ๋งมากครับ!! เป็นกำลังใจให้ครับ
เขียนบทแนะนำได้ดีมาก ๆ จนดูเหมือนว่าคนที่เข้ามาผ่าน GeekNews จะได้ข้อมูลมากกว่าคนที่เข้าไปดูที่ Repo ตรง ๆ เสียอีก ^^;

ถ้าตอนนี้มีใครใช้งาน Protobuf อยู่แล้วมาคอมเมนต์ไว้ น่าจะช่วยได้มากเลยครับ