Nói đến ứng dụng chat realtime, chắc ai cũng nghĩ ngay đến việc dùng thư viện hay service bên thứ 3 như websocket, Firebase RealTimeDatabase … phải không nào?
Mỗi công nghệ sẽ có ưu điểm, nhược điểm riêng, mà quan trọng nhất phải phù hợp với hệ thống hiện tại.
Vậy hãy cùng xem các kỹ sư Eureka tại sao chọn gRPC cho giải pháp của mình, và đã tối ưu nó như thế nào nhé.
Trước khi đi vào phần chính cùng tìm hiểu xem Eureka là công ty như thế nào đã nhé.
Công ty Eureka là công ty Nhật bản, được thành lập vào năm 2008, đến thời điểm hiện tại Eureka đã có 130 nhân viên.
Eureka đang vận hành 1 service về tình yêu và dịch vụ kết hôn lớn nhất Nhật Bản có tên là Pairs (Hay nói cách khác đây là 1 dịch vụ về hẹn hò thì đúng hơn).
Chức năng chính trong Pairs thì có rất nhiều nhưng mình chỉ điểm qua 1 số điểm chính thôi nhé:
Điểm mà mình thích nhất ở Pairs đó là mặc dù mình đăng kí tài khoản thông qua Facebook. Nhưng Pairs sẽ luôn lựa chọn ảnh “bạn gái” mà không cùng Friend trên Facebook với mình (kể cả Friend của friend cũng không hiển thị ra luôn).
Vào đó hẹn hò lén lút mà gặp phải bạn thân của vợ thì … Mà thôi nói đến đây các bạn tự hiểu. =))
Vậy đến đây các bạn cũng hiểu đôi chút về Pairs của Eureka rồi phải không.
Tiếp theo chúng ta đi vào vấn đề chính nhé.
Như mình giới thiệu ở trên, Pairs có 1 chức năng gọi là “chat hẹn hò”. Thế nhưng, hiện tại chức năng này đang thực hiện theo hình thức polling (tức là cứ mấy giây sẽ request lên api server lấy dữ liệu 1 lần).
Chính vì điều đó mà tin nhắn được gửi đến đối phương sẽ bị delay mất khoảng mấy giây. (Tức là sau khi A gửi tin nhắn cho B thì sau khoảng mấy giây tin nhắn mới hiển thị trên màn hình của B).
Vì đây là app hẹn hò. Nếu tin nhắn mà bị delay nhiều như thế thì về UX không được thân thiện cho lắm. Nên Eureka quyết định cải thiện chức năng chat này.
Bài toán đã có, bước tiếp theo là tìm hướng giải quyết. Nói là tìm hướng giải quyết nhưng việc lựa chọn công nghê phù hợp quả thật là 1 vấn đề đau đầu.
Ngoài gRPC ra thì còn có 1 số công nghệ khác nữa có thể giải quyết được bài toán này. Nói không xa đó chính là WebSocket đã có từ rất lâu đời.
Hay 1 công nghệ mà message Facebook đang sử dụng đó là MQTT.
1 số dịch vụ bên thứ 3 cung cấp cũng đang rất nổi tiếng như AWS AppSync, Firebase RealTimeDatabase cũng chuyên cung cấp giải pháp gửi nhận real time.
Có rất nhiều thứ khác nữa, nhưng do mỗi thứ có ưu điểm nhược điểm riêng, cộng với việc công nghệ đó phải phù hợp với project hiện tại. Nên các kỹ sư Eureka quyết định chọn gRPC cho giải pháp lần này.
Dưới đây là 1 số lí do:
Trên proto, chỉ cần gắn stream vào trong request lẫn response là có thể sinh ra được interface dùng cho việc truyền thông Two-way ở phía client.
Vì cách thực thi nó sẽ khác nhau với từng ngôn ngữ, nên để hiểu rõ hơn các bạn có thể xem qua tutorial ở đây nhé: gRPC tutorial
Cấu trúc hệ thống hiện tại đang như sau:
Cấu trúc sau khi đưa gRPC vào sẽ được thay đổi như sau:
Qua 2 cấu trúc bên trên, ta thấy sự khác nhau chủ yếu là ở phía receiver. Cụ thể như sau:
Dựa vào cấu trúc như này (dạng pub-sub) sẽ thấy không còn sự delay của việc Polling nữa. Thay vào đó phía receiver có thể nhận được message ngay tức thì.
Nhờ việc sử dụng RedisPubSub như là nơi giao tiếp giữa các server (mới và cũ) đã giúp cho người dùng có thể gửi và nhận message 1 cách tức thời.
Chức năng chat có thể nói là 1 trong những chức năng chính của hệ thống Pairs, nên việc có bug xảy ra có thể gây ảnh hưởng vô cùng lớn.
Vì phạm vi ảnh hưởng vô cùng lớn nên khi có bất kì bug nào thì việc rollback, detect lỗi là điều vô cùng quan trọng.
Trước khi release thì test code là điều đương nhiên phải làm. Thế nhưng để co hẹp phạm vi ảnh hưởng, Eureka đã nghĩ đến việc sẽ release chức năng chat mới này trên thiết bị Android trước. Sau khi chạy ổn định sẽ release tiếp trên iOS.
Chính vì điều đó mà sơ đồ cấu trúc hệ thống ở bên trên mới có phần API cũ và API mới là như thế.
File proto sẽ không nằm trong repository của các platform (ios/android/serverside) mà sẽ nằm ra 1 repository riêng biệt. Và dùng git submodule để chèn nó vào trong các repository của platform.
1 trong số những điểm mạnh của gRPC là có thể generate document và code 1 cách tự động nhờ sử dụng protoc.
Hơn nữa chúng ta có thể dễ dàng viết command line Make để generate ra document và code như bên dưới:
Đây là ví dụ về sample Document và proto đã được sinh ra nhờ command line phía trên:
Đúng quả là tiện thật.
Với gRPC đang gặp phải 1 vấn đề là rất khó khăn trong việc đo hiệu năng.
Thông thường, 1 request 1 response thì chỉ cần xem log nginx hay apache là có thể biết được request đó xử lý mất bao lâu, thời gian trung bình của latency là bao nhiêu.
Thế nhưng với dòng stream của gRPC thì lại khác, tương ứng với 1 request thì có bao nhiêu response, và khi nào sẽ trả về. Dữ liệu khi nào xảy ra, khi nào đến … đều không thể biết được.
Do đó nếu không cải thiện chỗ này thì khó có thể tính toán, đo đạc hiệu năng được.
Chính vì vậy, Eureka đã lưu 3 giá trị metrics ở bên dưới vào StackDriver & BigQuery và tiến hành đo đạc:
Ngoài ra nhờ có thể lấy được giá trị cụ thể này mà dễ dàng detect khi tổng thời gian vượt quá giá trị cho phép.
Về phương diện implement code thì không gặp nhiều khó khăn, thế nhưng về phương diện vận hành, monitoring server thì đang gặp rất nhiều vấn đề. Cần phải mapping lại các error code, các metrics thì mới có thể đo đạc đươc. Cụ thể như sau:
Mặc dù việc vận hành gRPC còn có chút try hard, nhưng với case tạo API mà sử dụng micro framework, hay với những dòng stream sử dụng HTTP/2 thì gRPC rất thích hợp và dễ dùng, dễ implement.
Nên nếu bạn nào đang có nhu cầu đưa gRPC vào hệ thống thì hi vọng bài viết này sẽ giúp các bạn 1 phần nào đó.
Nguồn: Devmaster Academy via viblo.asia