Categories
DevOps

WEBSOCKET: TỪ SOCKETIO ĐẾN SOKETI

Khoảng 8 năm trước, từ lúc bỏ mô hình Server Side Rendering (jQuery, Ajax…) và bắt đầu xây dựng hệ thống dựa trên mô hình Microservices & Single Page App (SPA) và sử dụng hoàn toàn frontend bằng Reactjs thì cũng là lúc bắt đầu chơi với WebSocket cho các tính năng tương tác hai chiều (Client < — > Server) theo thời gian thực.

Hoạt động của WebSocket khá đơn giản: trình duyệt kết nối tới một Socket server, lắng nghe trên 1 (hoặc nhiều) channel mình khai báo rồi…chờ message trên channel đó. Server muốn gửi dữ liệu cho trình duyệt của user thì chỉ cần đẩy message vào channel này, trình duyệt sẽ tự động nhận message và xử lý (ví dụ như hiển thị thông báo trên trình duyệt hoặc một hành động khác.)

Nhiều người khi nghe nói đến Websocket thì chỉ nghĩ đến các tính năng realtime chat, nhưng Websocket có nhiều ứng dụng, trong đó mình sử dụng nhiều nhất cho 3 chỗ trên trình duyệt: Nhận thông báo mới (Notification), Cập nhật dữ liệu cache trên trình duyệt (Realtime Data Update) và Trạng thái online của user (Online Presence).

Các phần mềm hỗ trợ WebSocket Server

Thời bấy giờ không có nhiều lựa chọn, ứng cử viên sáng giá nhất là Socket.IO: Open Source – Miễn phí, tự cài đặt trên server riêng và Pusher: Cloud, không cần cài đặt gì hết và trả phí.

Socket.IO thì hầu như không có nhiều đồ chơi, ngoài việc chỉ hỗ trợ trình duyệt kết nối socket tới server, không có cơ chế xác thực (Authentication), muốn làm gì thì phải chủ động code tính năng hết. Do mình làm ứng dụng cho dự án SaaS và multi-tenant nên khối lượng code viết thêm nếu làm trên SocketIO là quá lớn nên buộc phải tìm giải pháp khác, và lúc này Pusher đã xuất hiện.

Pusher cung cấp cơ chế WebSocket với nhiều tính năng, trong đó có 2 tính năng nổi bật nhất là hỗ trợ Authentication xác thực user kết nối và Presence Channel để biết ai đang online/offline. Ngoài ra, Pusher còn cung cấp các thư viện tích hợp cho cả Javascript (gắn ở trình duyệt) và PHP (gắn ở server) để xác thực và trao đổi dữ liệu realtime giữa client và server được đơn giản và nhanh chóng, rút ngắn thời gian phát triển.

Có một bất lợi duy nhất của Pusher là…chi phí. Do đặc thù của một hệ thống Realtime là số lượng kết nối thường xuyên đến socket server, nên chi phí tính dựa vào số lượng kết nối. Sau khi đánh giá thì với chi phí của Pusher so với những lợi ích nó mang lại thì quyết định chọn Pusher.

Thay thế Pusher bằng Soketi

Mười ngày trước, nằm trong tuần lễ cải tổ hệ thống, trong đó có hạng mục nâng cấp phân hệ Pusher sau một thời gian dài sử dụng, thì thấy chi phí hiện tại không ổn nếu scale lên vài ngàn socket connection dựa trên Pusher, cũng như áp dụng cho các khách hàng outsourcing.

Thật may mắn là đã tìm ra Soketi, một open source cài đặt trên server của mình và cung cấp các tính năng gần như tương tự của Pusher. Và đặc biệt quan trọng là tương thích hoàn toàn với các thư viện kết nối ở phía Javascript và PHP, tức là không phải thay đổi cơ chế kết nối và lắng nghe message, chỉ cần cài Soketi (có hỗ trợ docker), sau đó thì config trỏ lại kết nối đến Soketi Websocket server vừa cài là xong.

Sau một tuần triển khai lên các môi trường dev và production cho các dự án thì thấy hoàn toàn ổn định, kết quả này cũng là cảm hứng cho bài viết chia sẻ công nghệ này. Hy vọng anh chị em có một hệ thống Websocket ngon, bổ rẻ để xây dựng các tính năng realtime cho môi trường web.

Categories
Technology

Vũ trụ Nextjs và Headless CMS

Sau nhiều ngày chờ đợi để xem NextJS có ra bản 13.5 hay không thì cũng không chịu được nữa (nằm ở v13.4 đã gần 3 tháng) và đành khởi công dự án xây dựng Public CMS Framework (hay nói kiểu nhà quê là làm cái website) với phiên bản NextJS 13.4.12.

Server Side Rendering (SSR) với PHP

#Cropcom, mỗi một Public CMS Framework được xây dựng thì xác định tối thiểu phải 5 năm sau mới thay đổi công nghệ nên việc lựa chọn công nghệ nền ban đầu ảnh hưởng rất lớn đến trải nghiệm phát triển tính năng của team, cũng như phải “chịu đựng” trong quá trình xây dựng tính năng nếu lỡ nó lạc hậu hoặc team đó bỏ rơi không phát triển tiếp công nghệ nền.

Nếu bạn quan tâm thì Public CMS Framework gần nhất của công ty do Tuấn xây dựng là dựa trên PHP 7, sử dụng một phần của Symfony HTTPFoundation để xây dựng core, sử dụng Smarty cho tầng View (HTML, CSS..), còn layer Model & Controller thì kết nối đến hệ thống microservice theo cơ chế Headless CMS. Public CMS này thực ra hiện tại vẫn ổn vì nó tương thích hoàn toàn với khả năng Server Side Rendering (SSR) để tận dụng tối đa khả năng onsite SEO.

NextJS cho SSR & CSR trong tương lai

Hướng cũ này có một bất lợi duy nhất là, sẽ khó khăn nếu tiếp cận xây dựng các tính năng không cần SEO (sau màn hình đăng nhập) như thông tin tài khoản, các tính năng sau khi đăng nhập (submit này nọ, tương tác với thành viên khác…). Lỡ theo kiến trúc này nên phần lớn các tính năng đòi hỏi thuần Client Side Rendering (CSR) toàn phải xài jQuery và code chay, rất khó mở rộng theo nhánh này. Mà ngày nay, làm gì có website nào chỉ thuẩn SEO content, nếu vậy xài WordPress cho rồi, viết framework đồ chi.

Nếu muốn viết lại Framework mới cho Public CMS thì phải giải quyết được 2 bài toán là cần có SSR, hỗ trợ được các công nghệ CSR như Reactjs…để vừa đạt hiệu quả làm SEO, vừa hỗ trợ team dev phát triển tính năng một cách hiệu quả, nhanh chóng. Thế là đến với NextJS. Hiện tại sau hơn 4 năm chạy với Nextjs (từ nextjs 8.x đến nay thì phiên bản 13.4 được coi là siêu ổn để giải quyết 2 vấn đề lớn mà Tuấn cần giải quyết cho Public CMS của mình.

Lựa chọn UI Component Library

Tuy nhiên, sau khi trào lưu di dời sang Nextjs thì sẽ phát sinh 1 vấn đề khác là không có một bộ Component UI Library hoàn hảo. Và vấn đề này luôn là mối quan ngại khi xây dựng CMS với Nextjs bởi chưa có “cái nào” mà mình đánh giá là xài được. Radix UI thì có vẻ phức tạp, ngôi sao mới nổi Shadcn thì tạo ra các giao diện không mấy thân thiện với người dùng bình thường nên chủ yếu shadcn để xây các sản phẩm hơi hướng tinh giản và tech savy. Chưa kể nhiều UI Lib không tương thích với React Server Component.

Dường như vũ trụ Nextjs đã lắng nghe, và sau 1 ngày xây dựng thì dự án NextUI (không liên quan đến Vercel) hôm qua đã ra mắt phiên bản 2.0 với RẤT nhiều cải tiến mà sẽ dùng tốt cho NextJS 13 (dùng App Router). Việc thấy được sự ra mắt của NextUI 2.0 chính là cảm hứng cho mình chia sẻ bài viết này cũng như mọi người có thể hình dung xây dựng một Public CMS cần có nhiều yếu tố cân nhắc vì tính dài hạn và hướng người dùng (UX) & hướng dev (DX).

NextUI Website: https://nextui.org/

Trong tương lai nếu có lib nào xịn hơn thì sẽ xem xét và cân nhắc, nhưng cho đến hôm nay thì mình thấy NextUI là chân ái và sẽ apply cùng với TailwindCSS cho toàn bộ các design của CMS.

Categories
DevOps Technology

CHỌN CX HAY DX?

Dạo gần đây trên twitter có rất nhiều chỉ trích từ cộng đồng làm frontend về việc bản #Nextjs 13.4 cho tới 13.6 có trải nghiệm compile ở máy rất tệ khi sử dụng kiến trúc mới là App Router. Thời gian mỗi lần hot reload tính bằng giây và bản thân Tuấn đang phát triển cho hệ thống IDP của #cropany cũng thấy trải nghiệm tương tự, gần đây mỗi lần nhấn lưu là banh xác, chờ vài giây và compile vài ngàn module.

Việc này ảnh hưởng lớn đến #DX – hay gọi dễ hiểu là Trải nghiệm của lập trình viên (Developer Experience), cái được cộng đồng đánh giá công ty Vercel (hay dự án Nextjs) là một công ty có DX rất tốt, riêng mình nói về vụ DX thì Vercel là dẫn đầu thị trường thì nay lại bị chê bai rất nhiều.

Tuy nhiên, giá trị của kiến trúc App Router từ bản Nextjs 13.4 là không thể chối từ, nó đem lại trải nghiệm tốt hơn về thiết kế UI, Render flow (page, layout, template, server component, server action…) và cải thiện SEO ở mức tốt nhất cho các dự án CMS/Ecommerce. Đây cũng là lý do chính mà cả bộ sậu Vercel đầu tư rất nhiều vào kiến trúc App Router (thư mục “app”) để thay thế cho kiến trúc thư mục “pages” cũ. Những lợi ích này có giá trị rất lớn cho #CX – hay gọi dễ hiểu là Trải nghiệm của khách hàng (Customer Experience) 👍.

Các cuộc tranh cãi nổ ra kiểu nếu DX của App Router còn tệ hại như vậy thì chúng tôi sẽ bỏ đi, sẽ Vite + ReactJs, sẽ Angular, sẽ Gatsby 🤭…mà hoàn toàn phủ nhận giá trị của CX mà Nextjs mang lại.

Lịch sử đã cho thấy, chúng ta (developer) sẽ sẵn sàng đánh đổi 1 chút DX của mình để khách hàng được trải nghiệm tốt nhất. Chúng ta đã từng có giai đoạn dành cả tiếng đồng hồ để compile một phần mềm trong mỗi lần thử, dành cả ngày để render cái scene 3D cho đẹp hơn xí,… mà giờ có vài giây cũng kêu ca. Tuy nhiên, nếu sự chờ đợi dành cho quá trình phát triển để đem lại trải nghiệm cho khách hàng (CX) tốt hơn thì hoàn toàn xứng đáng. Vì trải nghiệm khách hàng khi sử dụng website tốt sẽ đem lại tiền cho doanh nghiệp.

Nói đi cũng phải nói lại, nếu DX của hệ thống tệ và đối thủ làm tốt hơn thì cộng đồng có thể quay lưng (như cách chúng ta đã quay lưng với nhiều thứ để đến với Nextjs). Hoặc nếu trong một dự án mà DX tệ thì sẽ ảnh hưởng không tốt đến nguồn lực dev của công ty. Mọi người sẽ tiếp cận dự án khó hơn, phát triển tính năng lâu hơn, chỉnh sửa, nâng cấp cũng vất vả…

Và sáng nay thật nhanh chóng, NextJs đã ra bản 13.4.8 với rất nhiều cải thiện để tối ưu cho DX sau rất nhiều càm ràm (và đòi bỏ đi) trên mạng. Quả thực, đi theo Nextjs từ bản 8.x tới giờ thì Nextjs không bao giờ làm ta thất vọng và phải nói trải nghiệm DX và CX từ Nextjs luôn làm ta ngạc nhiên và xứng đáng đầu tư toàn bộ stack ở cms/ecommerce đi theo Nextjs. Và việc release này cũng làm cảm hứng cho bài chia sẻ này.

Categories
Technology

Học Đại học CNTT nào?

Cách đây vài ngày có đọc một trao đổi trên Reddit về việc một OP hỏi là nên chọn học CNTT ở đại học Tôn Đức Thắng hay đại học FPT. Có khá nhiều ý kiến, chửi OP ngu có, chửi mấy thằng chửi người ta ngu cũng có và cũng có mấy ý khá thô nhưng thật đó là học trường nào ra cũng như nhau vì cũng không phải trường top và cầm tấm bằng tốt nghiệp của 1 trong 2 trường này là same same.

Tất nhiên sẽ có nhiều quan điểm bên ngoài là thời nào rồi mà còn phân biệt bằng đại học, miễn ra làm được việc là được, không nên kì thị blah blah…Vậy thì quý vị hãy nhìn xung quanh để xem vì sao các trường top được tranh giành ứng tuyển, những quản lý cấp cao hầu hết đều nằm ở trường top, hoặc mức lương trung bình của các bạn tốt nghiệp trường top sẽ cao hơn các bạn tốt nghiệp trường non-top.

Nhìn bề ngoài thì có vẻ kì thị, nhưng thực ra vấn đề lớn tạo nên điểm khác biệt ở hai môi trường này là “Bạn có gì trước khi vào trường top” và “Bạn sẽ có gì sau khi ra trường top”. Nếu xoay quanh 2 câu hỏi này thì sẽ dễ hình dung hơn vì sao có sự chênh lệch và phân biệt đối xử này từ thị trường tuyển dụng & việc làm IT.

Để vào trường top các bạn ít ra phải là một tay đáng gờm (bên cạnh sự may mắn, mấy ông rớt hay nói mấy ông đậu ăn hên) nên việc bạn học ở đâu không quan trọng (tất nhiên bạn sẽ chọn học trường top). Và với trí não (hoặc bà đãi) như vậy thì việc sau này đi làm gặp nhiều thuận lợi hơn là điều dễ đoán.

Tiếp đến, học trong trường top theo mình thấy được nhà trường đào tạo các môn ban đầu nhìn vào hoặc từ bên ngoài nhìn vào tưởng chừng như nhảm nhí, dư thừa nhưng thật ra càng đi làm mình càng thấy cực kì hay và thấy may mắn nhờ những môn học đó gieo vào đầu mình những hạt giống kiến thức nền tảng.

Ví dụ Tứng học khoa CNTT ở trường KHTN HCM (nghe nói trường này cũng đã từng đứng top), những môn mà lúc học thấy khá vô nghĩa như thời này mà còn học Assembly để làm gì, rồi còn học thiết kế mạch logic, toán rời rạc, mạng máy tính cơ bản, blah blah…Và được ca tụng nhất là môn Triết học. Riêng về cái triết học thì lúc học mình khá hứng thú tới khoảng 20-30% gì đó trong thời gian học (còn lại chủ yếu ngủ hoặc trốn) nhưng những bài học về triết học giờ ngẫm lại có ý nghĩa, ví dụ “Biến đổi về lượng dẫn đến biến đổi về chất”, nghe nhồi sọ nhưng thật ra nếu bạn làm ở ngành thiết kế hệ thống, với lượng truy cập ngày một lớn (lượng) thì bạn không thể dùng giải pháp hiện có mà phải thay đổi giải pháp (chất) để thích nghi, đó chỉ là một ví dụ nhỏ của việc học…triết học.

Do đó, nếu lỡ không được học ở một trường giúp tiếp cận các nền tảng công nghệ ở cấp độ cơ bản thì bạn có thể tự trang bị các kiến thức này. Việc tự trang bị kiến thức nền sẽ giúp bạn không cần bằng đại học trường top vẫn cạnh tranh với các ứng viên trường top, hay bà con thường gọi là “cần cù bù thông minh”.

Chỉ còn vài ngày nữa là đến kì thi, hy vọng các sĩ tử đạt được trường tốt mà mình ngắm.

Fighting!!!!

Categories
Miscellaneous

New Year’s Resolution of 2023

Vậy là lại đến ngày cuối cùng của năm, lại ngồi viết một vài dòng để tóm tắt lại năm vừa rồi cũng như đặt ra một số chỉ tiêu cho năm mới 2023.

Năm 2022 đánh dấu sự ảnh hưởng dài và rộng của Covid-19 đến xã hội, kéo theo ảnh hưởng đến toàn thị trường, trong đó có thị trường phần mềm mà Tuấn trực tiếp tham gia. Nếu dành một từ để miêu tả năm 2022 của Tuấn thì đó là CHÁN.

2022 – Một năm chán nản

Về làm ăn thì với mục tiêu ban đầu là không nhận thêm dự án outsourcing, đây là một chiến lược sai lầm của mình trong năm nay, kèm theo việc đánh giá thấp duy trì dòng tiền khiến cho dòng tiền rơi vào khủng hoảng, xoay sở để hết năm 2022 đúng là một trải nghiệm không muốn có, tuy nhiên cũng dạy cho mình nhiều điều về cách quản lý dòng tiền cũng như chiến lược kinh doanh từ nay về sau.

Do không đẩy mạnh nhận outsourcing nên đã ra mắt được phiên bản thử nghiệm của dự án Cropany, đây được coi là dự án chính của công ty trong 2023.

Nhân sự không tăng nhưng giảm bớt nên cũng coi là không thành công trong khâu mở rộng công ty. Tuy nhiên, việc không mở rộng team cũng coi là may mắn để giúp duy trì dòng tiền trong năm 2022 vừa qua.

Tuy nhiên, cũng có một chút thành tựu là đã di chuyển sang một văn phòng rộng lớn và thoải mái hơn, cũng như vào trung tâm (ở Quận 10) thay vì ở Q. Tân Phú như trước đây.

Về gia đình thì không đóng góp nhiều về mặt tài chính vì tập trung xoay sở để giúp công ty tồn tại. Tuy nhiên, có niềm vui là các con đã trưởng thành hơn một chút và học cùng trường.

Về bạn bè thì nhận ra xung quanh mình có nhiều người bạn tốt, sẵn sàng giúp đỡ trong những lúc mình gặp hoàn cảnh khó khăn.

Về cá nhân thì nhận thấy trình độ của bản thân vẫn được phát triển, xây dựng được một số kiến trúc phần mềm mới giúp ích nhiều cho việc xây dựng phần mềm. Số lượng sách đọc khá là ít (khoảng 20 cuốn) nên cũng chỉ là đọc ở mức cơ bản.

Về sức khoẻ thì không giảm được ký nào mà lại tăng 1 2 ký bởi vì áp lực quá lớn khiến không có tâm trạng để…giảm cân.

Kế hoạch 2023

Sau khi nhận ra được nhiều lỗ hổng trong chiến lược kinh doanh và phát triển sản phẩm nên hy vọng năm 2023 sẽ có các hướng phát triển an toàn và bền vững hơn.

  • Sẽ tập trung phát triển tiếp dự án Cropany để ra mắt một phần mềm quản lý công ty miễn phí top đầu VN.
  • Lấy lại phong độ đọc 50 cuốn sách.
  • Đi du lịch trong và ngoài nước ít nhất một lần
  • Đẩy mạnh nhận 5-7 dự án outsourcing, doanh thu tăng gấp 5 lần so với 2022.
  • Tham gia chia sẻ ít nhất 5 lần tại cuộc hội thảo / meetup offline
  • Viết một cuốn sách miễn phí về công nghệ để giúp người mới.
  • Tăng 100% nhân sự.

Như hầu hết mọi người, mục tiêu đặt ra để giúp mình đánh giá lại những gì kì vọng và đạt được để phát triển và hoàn thiện bản thân hơn. Tự thấy 2022 đã giúp mình học và hiểu được nhiều điều nên hy vọng 2023 sẽ là một năm thắng lợi và thành công.

Tuấn cũng hy vọng các bạn sẽ có một năm 2023 tràn ngập niềm vui và gặt hái thành công hơn nữa.

Categories
Mobile

Cài đặt môi trường React Native 0.70 trên Mac M1

Chào các bạn, hiện tại nếu làm theo các hướng dẫn trên web chính thức của reactnative.dev thì có thể bạn sẽ không thể cài đặt thành công môi trường để chạy được React native 0.70 trên M1.

Mình viết bài này để chia sẻ nhanh một số bước mà mình đã cài đặt môi trường thành công và chạy được React Native. Một số thông tin cấu hình của máy mình. Mac M1, hệ điều hành Ventura 13.0, React Native 0.70.

Ghi chú bằng tiếng Anh nên mọi người thông cảm:

Step 1: Install “rbenv”

> brew install rbenv

Step 2: install ruby 2.7.5 (React native 0.70 required)

> rbenv install 2.7.5

> rbenv global 2.7.5

Step 3: Update ~/.zshrc, append this line:

eval "$(rbenv init - zsh)"

Restart zsh

> source ~/.zshrc

Step 4: install sample project

> npx react-native init MyTestApp

(ESC on select cocoapod installations question). We will install later

Step 5: Go to ios

> cd ios

Step 6: Install cocoapods via brew

> brew install cocoapods

Step 7: Install ffi

> sudo gem install ffi 

(there is no need arch.. as online tutorials ^^!)

Step 8: pod install

Run bundle

> bundle install

Update current repository to latest version (to prevent olddate repo)

> arch -x86_64 pod repo update

Finally, run pod install

>  arch -x86_64 pod install 

Categories
DevOps

Công bằng khi xử lý bất đồng bộ ở Microservice

Suốt tuần qua mình tập trung xử lý một bài toán khá “kinh điển” trong mô hình multi-tenant là đem đến “sự công bằng” (fairness) đối với các xử lý bất đồng bộ (async process). Nhận thấy vấn đề và giải pháp này sẽ giúp ích nhiều cho các anh em làm SaaS nên mình chia sẻ cách triển khai trong bài viết này.

Bài viết này dành cho những bạn đã từng thiết kế hệ thống theo mô hình bất đồng bộ như sử dụng Job Queue và đang có mô hình kinh doanh Multitenancy.

Vấn đề

Nếu bạn xây dựng hệ thống theo kiến trúc trúc Microservice thì bạn sẽ thường xuyên đối mặt với mô hình xử lý bất đồng bộ (async processing). Bởi vì đặc thù các service/process hoạt động tách biệt, để tránh ảnh hưởng tới thời gian chờ xử lý thì hầu hết hết các business logic phức tạp đều chạy bất đồng bộ (async). Trong trường hợp của Cropany là tính năng cập nhật tồn kho cho sản phẩm.

Theo như thiết kế hiện tại, tính năng “Số lượng tồn kho sản phẩm” được thiết kế theo pattern CQRS/ES. Tức là mọi thao tác liên quan đến tồn kho như Nhập kho (mua hàng), Xuất kho (bán hàng) đều có những record ghi nhận thao tác nhập xuất sản phẩm, sau đó sẽ kích hoạt API bất đồng bộ xử lý tính toán số tồn riêng của từng sản phẩm vào database (elasticsearch).

Trước đây, để tính toán tồn kho của sản phẩm, thì hệ thống có 1 queue chứa danh sách ID các sản phẩm cần cập nhật tồn kho. Khi 1 sản phẩm có tương tác nhập xuất thì ID sản phẩm này sẽ được đẩy vào queue, và worker sẽ lắng nghe trên queue này, các worker sẽ lấy đều đặn một số lượng nhất định ID (ví dụ: 10 ID/lần xử lý) và tiến hành tính toán số tồn và lưu vào database.

(Hình minh hoạ quá trình xử lý bất đồng bộ. Nguồn: Medium)

Do theo kiến trúc queue FIFO nên ID sản phẩm nào được đưa vào trước thì sẽ được worker xử lý trước và xử lý tuần tự cho tới khi queue này không còn message nào. Nếu mô hình của bạn là Single-tenancy thì sẽ không có vấn đề gì, nhưng nếu bạn đang theo mô hình Multi-tenancy và số lượng tenant khá lớn (ví dụ hơn 10,000 tenant) thì vấn đề có thể sẽ khá lớn.

Hãy hình dung, trong số các tenant, vào 1 thời điểm sẽ có tenant (gọi là Tenant-A) đẩy vào queue 5000 ID sản phẩm (họ đang nhập kho) và liền ngay sau đó có tenant khác (gọi là Tenant-B) chỉ xuất kho 1 sản phẩm (bán hàng). Theo như kiến trúc ban đầu thì queue sẽ có 5001 ID sản phẩm, và worker sẽ tiến hành lấy tuần tự số lượng ID cho phép xử lý (ví dụ 10 ID/lần xử lý) và như vậy, Tenant-B sẽ phải chờ worker xử lý hết 5000 message của Tenant-A mới đến lượt mình. Hiện tại không có sự ưu tiên nào giữa các tenant nên Tenant-B có thể bị coi là “thiệt thòi” hơn so với Tenant-A.

(Hình minh hoạ các message của các tenant được đẩy tuần tự vào queue để xử lý tuần tự. Nguồn: medium)

Trong ví dụ trên thì chỉ có 2 tenant, giả sử hệ thống multi-tenancy của bạn có 10,000 khách hàng và 10,000 tenant này đều nhập xuất kho với số lượng chênh lệch thì tenant cuối cùng đẩy ID sản phẩm vào queue sẽ phải chờ lâu nhất. Giải pháp hướng đến là đem lại “sự công bằng” cho các tenant nếu như mọi tenant đều có đặc quyền như nhau. Trong trường hợp của Cropany là khách hàng nào cũng miễn phí, dù dùng ít hay nhiều đều phải có sự công bằng và độ trễ ngang nhau khi sử dụng.

Giải pháp không hiệu quả

Giải pháp ban đầu có thể nghĩ ngay tới là đối với mỗi tenant thì mình sẽ có 1 queue riêng và tương ứng với mỗi queue sẽ có 1 worker lắng nghe và xử lý.

Về mặt performance thì giải pháp này không hiệu quả vì đồng thời có hàng ngàn worker tính toán tồn kho thì bottleneck sẽ rơi vào database chứa các giao dịch nhập xuất. Thay vì giải pháp cũ thì mỗi lần worker chỉ vào xử lý 1 số lượng nhất định và kiểm soát được (ví dụ 10 ID Sản phẩm / lần) thì bây giờ số lượng worker lớn làm tăng tải của quá trình xử lý, trong khi throughput của hệ thống chỉ cho phép 10 ID Sản phẩm / lần.

Về mặt kinh tế thì hoàn toàn không khả thi, tài nguyên để hỗ trợ chạy hàng ngàn worker và hàng ngàn queue không hề nhỏ và nó lại tăng tịnh tiến (linear) theo số lượng tăng thêm của tenant. Trong trường hợp của Cropany thì càng không thể vì chúng mình không thu phí khách hàng. Ngoài ra, sẽ có những tenant rất ít hoạt động, worker vẫn phải duy trì trong khi không có xử lý thì là một sự lãng phí.

Giải pháp của Cropany

Sau khi cân nhắc về hiệu suất, kinh tế và khả năng bảo trì nâng cấp thì mình quyết định sử dụng mô hình 1 queue, một worker như ban đầu để đảm bảo worker hoạt động đúng công suất cho phép và không gây áp lực lên hệ thống chung (các tính năng khác liên quan đến database). Tuy nhiên, khi phát sinh nhập xuất kho sản phẩm thì thay vì đẩy trực tiếp vào queue, các ID này sẽ được đưa vào một SET trong Redis, và mỗi tenant sẽ có một SET riêng (key riêng).

Giới thiệu nhanh về SET trong Redis, SET cho phép lưu trữ một danh sách các value không trùng. Trong trường hợp này, nếu ID sản phẩm đã tồn tại trong SET của tenant nào rồi thì khi phát sinh giao dịch, thêm 1 value vào SET mà đã tồn tại value này thì SET sẽ không lưu thêm, luôn đảm bảo value là không trùng.

Sau khi các tenant có các SET riêng thì mình viết một chương trình điều hướng nho nhỏ (nodejs), đều đặn đọc tất cả các SET này ra và cắt lát theo chiều dọc qua toàn bộ các tenant và đẩy vào queue thông thường. Theo cách này thì tenant dù có ít hay nhiều đều sẽ được xử lý song song theo từng phiên. Giả sử có 10k tenant và tenant nào cũng có ID sản phẩm cần xử lý thì bộ điều hướng này sẽ lấy mỗi tenant 1 ID và đẩy vào queue. Queue có thể chứa hàng triệu message, tuy nhiên, thứ tự các message khi thêm vào đã đảm bảo gần như công bằng cho các tenant.

(Hình minh hoạ bộ điều hướng cần tiền xử lý các message trước khi đẩy vào queue)

Sau khi đẩy vào queue thì bộ điều hướng này sẽ xoá ID khỏi SET trong Redis để tránh quá trình xử lý trùng lập.

Có một lưu ý nho nhỏ là bộ điều hướng này cần chạy theo interval (đơn vị giây) để đảm bảo có các tenant mới phát sinh SET mới thì vẫn được đưa vào queue chính. Hình minh hoạ bên dưới là quá trình mình visualize bộ điều hướng để debug quá trình cắt lát cho các bạn dễ hình dung.

Trong hình là bộ điều hướng chạy 2 phiên. Mỗi phiên tìm thấy 13 tenant (13 màu), và chỉ có 6 tenant có message cần xử lý, mỗi phiên bộ điều hướng sẽ lấy 6 message từ 6 tenant và đẩy vào queue.

Mở rộng

Như vậy, với kiến trúc này thì vẫn đảm bảo cơ chế scale hệ thống như là tăng cường throughput của worker, tăng số lượng worker nếu muốn xử lý nhanh hơn khi hệ thống cho phép.

Bên cạnh đó, nếu có cơ chế ưu tiên giữa các tenant thì có thể tăng cường queue riêng để áp dụng 1 số quyền lợi cho các tenant được ưu tiên.

UPDATED: Sau khi update lên UI thì mình chuyển sang SORTED SET thay vì SET nhé các đồng code. Sorted set sẽ lưu thêm score để đảm bảo độ ưu tiên và mình lấy timestamp làm score, còn SET thì không lưu thứ tự nên sẽ ko thể hiện rõ FIFO khi thêm vào SET. 


Bài viết sử dụng một số hình ảnh từ bài viết https://medium.com/thron-tech/multi-tenancy-and-fairness-in-the-context-of-microservices-sharded-queues-e32ee89723fc cũng nói về đề tài fairness, các bạn có thể tham khảo cách tiếp cận khác của tác giả bài viết này.

Categories
Miscellaneous

New Year’s Resolution of 2022

Chưa thấy năm nào trôi qua nhanh vùn vụt như năm 2021, mới ngày nào còn ngồi viết resolution cho năm 2021 thì hôm nay đã là ngày cuối cùng của năm 2021. Với tình hình chung của xã hội thì năm 2021 được coi là một năm đầy biến động tiêu cực và tác động xấu của dịch bệnh Covid19 đã thể hiện rõ nét trong năm nay.

Tuy nhiên, nếu dùng một từ để đánh giá chung cho năm 2021 đối với mình thì đó là từ AN TOÀN: gia đình an toàn, kinh doanh an toàn và sức khoẻ an toàn…

2021 – Chậm rãi và không nổi bật

Về tổng quan so với 2020 thì 2021 là một năm khá chán vì 100% các chỉ tiêu không được hoàn thành, có quá nhiều mối bận tâm khiến việc tập trung thực hiện các mục tiêu bị ảnh hưởng.

Về kinh doanh thì kiếm đủ tiền duy trì các hoạt động của công ty. Cũng may mắn là còn 1 vài khách hàng cũ tin tưởng và tiếp tục outsourcing mở rộng các dự án hiện có. Và 2021 hoàn toàn không mở rộng thêm mảng outsourcing.

Đối với mảng SaaS thì Movecrop được nhiều khách hàng mới tin dùng vì vai trò của việc giao nhận hàng trở nên thiết yếu trong thời điểm 2021. Tất nhiên không đột phá, nhưng đây cũng là tín hiệu tốt trong thị trường này. Teamcrop và Basecrop vẫn là hai sản phẩm chiến lược khác của công ty ở mảng SaaS.

Và lần đầu tiên mới có thể thực hiện mô hình Work From Home đúng nghĩa suốt mấy tháng trời (do cách ly xã hội) và phát hiện là mô hình này cũng không hiệu quả bằng mô hình làm tại công ty.

Năm nay không thay đổi về mặt nhân sự nên có thể coi là không đạt chỉ tiêu đề ra là phải gấp đôi nhân sự, bên cạnh đó thì công ty đã đổi sang văn phòng mới rộng hơn một xíu, sáng sủa và thoải mái hơn trong đầu năm 2021.

Về gia đình thì 2021 có thể nói là năm mà ở cùng với gia đình nhỏ nhiều nhất vì gần 6 tháng cách ly xã hội và loanh quanh với gia đình mà thôi. Có một may mắn là đợt cách ly xã hội này diễn ra ở Long An nên cũng thoải mái đầu óc hơn và các thành viên trong gia đình cũng có không gian lớn hơn là mấy chục mét vuông ở Sài Gòn.

Sức khoẻ có phần bị ảnh hưởng nhưng may mắn là các thành viên đều an toàn hết năm 2021. Năm nay không thực hiện được chuyến du lịch xa nào nên có thể coi là khá thiệt thòi so với các năm trước, nhưng an toàn là trên hết nên đành “chấp nhận ở nhà”.

Về cộng đồng và bạn bè thì cũng như năm ngoái (2020), không có quá nhiều thời gian và điều kiện để tổ chức các buổi gặp gỡ để chia sẻ kiến thức với cộng đồng. Tuy nhiên, những người bạn lâu năm thì vẫn gặp và tám bình thường và may mắn là mọi người ai cũng an toàn và khoẻ mạnh.

Về cá nhân thì hiện tại thói quen đọc sách đã bị ảnh hưởng do giai đoạn covid ảnh hưởng đến thời gian biểu sinh hoạt cũng như thời điểm và thời lượng đọc sách. Chỉ đọc được 50 cuốn sách (đạt 1/3 chỉ tiêu đề ra) nhưng phần lớn là tiểu thuyết vì khó mà tập trung đọc các sách đòi hỏi nhiều đầu óc.

Cuối năm thì lại tăng cân như thời điểm 2020 và tháng 12 đã tiến hành mua xe đạp để thay đổi phương pháp thể dục rèn luyện sức khoẻ.

Về kiến thức chuyên môn thì tự thấy trình độ bản thân đã tăng hơn “một chút” so với năm trước, đặc biệt là sử dụng và thiết kế framework ở frontend và backend. Bên cạnh đó, bắt đầu tìm hiểu một chút về công nghệ blockchain và một số kỹ thuật lập trình liên quan đến công nghệ mới này và hy vọng có cơ hội sử dụng trong năm nay.

Kế hoạch 2022

Năm nay dự kiến sẽ là một năm đột phá và có ảnh hưởng mạnh đến sự nghiệp và cuộc sống cá nhân. Nói hoành tráng vậy thôi chứ vẫn hy vọng thực hiện hết các mục tiêu dưới đây trong năm 2022:

  • KHÔNG nhận thêm khách hàng Outsourcing mới và chỉ duy trì hỗ trợ tốt nhất các khách hàng hiện tại
  • Xây dựng một sản phẩm SaaS mới sẽ đem lại nhiều giá trị hơn cho doanh nghiệp trong và ngoài nước
  • Làm “một cái gì đó” liên quan đến công nghệ blockchain
  • Doanh thu gấp 1.5 lần năm 2021
  • Du lịch 2 lần cùng gia đình và công ty
  • Đọc xong 100 cuốn sách
  • Tham gia 4 buổi meetup về khởi nghiệp/lập trình
  • Viết 10 bài blog
  • Lên ý tưởng viết tiểu thuyết đầu tiên
  • Tăng trưởng 50% nhân sự

Ai cũng có kế hoạch và mục tiêu của mình ở 2022 và hy vọng mọi người sẽ hoàn thành được các mục tiêu đã đề ra. Nhân dịp này, chúc các bạn độc giả một năm mới khoẻ mạnh, luôn gặp may mắn, niềm vui trong công việc và cuộc sống.

Happy new year!

Categories
Review sách

Review sách Accelerate

Nhớ cách đây 6 năm, #CropCom bắt đầu dấn thân vào con đường DevOps bán chuyên với Monolithic, SVN, Jenkins…cho đến 4 năm trước với sự trưởng thành hơn về stack DevOps với kiến trúc Microservices, Git, Gitlab CI… cho thấy sự thay đổi công nghệ liên tục cũng như giá trị mà nó mang lại.

Mở đầu tháng 2 cũng như mở màn chuỗi ngày “bị” nghỉ Tết với một cuốn sách khá hay về DevOps là Accelerate. Đây là một cuốn sách nói về lợi ích của phương pháp xây dựng quy trình phần mềm tinh gọn và Devops, dựa trên một nghiên cứu hàng năm trong hơn 4 năm của nhóm tác giả, với gần 30.000 người làm DevOps tham gia khảo sát.

Nếu để ý thì một trong những tác giá là Gene Kim, tác giả của 2 cuốn tiểu thuyết hư cấu nổi tiếng  bàn về áp dụng DevOps là The Phoenix Project (Dự án Phượng Hoàng).

Ở phần đầu, sách đi sâu vào việc tìm hiểu mối tương quan giữa việc áp dụng quy trình xây dựng phần mềm theo phương pháp Lean, Devops và giá trị cho doanh nghiệp, tổ chức như cải thiện hiệu quả công việc, văn hóa công ty và chuyển đổi số. Trình bày chi tiết 24 khía cạnh DevOps thuộc 5 nhóm lớn bao gồm: Continuous delivery, Architecture, Product and process, Lean management and monitoring, Culture.

Ngoài ra, ở phần 2 (là phần mình thích nhất trong sách) các tác giả đưa ra những phương pháp, lý do dẫn đến việc thiết kế bảng khảo sát (survey) của mình để đảm bảo khách quan nhất có thể như các tip lựa chọn phương pháp lấy dữ liệu, phương pháp thống kê, cách sử dụng từ ngữ, đặt câu hỏi sao cho tránh các thiên kiến (bias) hoặc đóng khung (framing) và hiểu lầm.

Nếu bạn là một nhà quản lý công nghệ của công ty hay tổ chức (Vd: CTO, CIO..) thì không thể bỏ qua cuốn sách này nếu muốn tìm hiểu sâu hơn các phương pháp đánh giá, xây dựng quy trình tinh gọn cho các đội phát triển phần mềm. Đặc biệt là những ai chỉ nghe nói đến DevOps nhưng chưa thật rõ công dụng và hiệu quả của nó lên giá trị của doanh nghiệp. Khuyến đọc.

“Nearly every company relies on software, delivery performance is critical to any organization doing business today. And software delivery performance is affected by many factors, including leadership, tools, automation, and a culture of continuous learning and improvement.”

“You can’t buy or copy high performance. You will need to develop your own capabilities as you pursue a path that fits your particular context and goals. This will take sustained effort, investment, focus, and time.”

– trích Accelerate (Nicole Forsgren, Jez Humble & Gene Kim)

Categories
Review sách

Review sách “101 UX Principles”

Đọc cuốn này được 2 ngày rồi, nay cuối tuần có thời gian ngồi review và chia sẻ thêm thông tin về sách này cho mọi người. Không giống hầu hết những sách về UX khác trên thị trường thiên về lý thuyết thiết kế, hơi hàn lâm và nói chung chung khó hiểu, dùng nhiều não, hay mình hay gọi là sách chiến thuật UX (strategy), cuốn 101 UX Principles của Will Grant là một cuốn theo trường phái chia sẻ kinh nghiệm, mẹo cụ thể (tactic) nên đọc cực kỳ dễ hiểu.

Nếu bạn là một người mới với thiết kế UI/UX, đặc biệt là trong mảng website và ứng dụng di động thì không thể bỏ qua sách này. Rất nhiều lời khuyên bổ ích mà ngay cả những “chuyên gia UX” cũng đôi khi bị bỏ qua hoặc “lờ đi” vì làm biếng.

Từ việc dùng chữ thế nào, thiết kế các input cho form, trang tìm kiếm đến các khái niệm liên quan đến tâm lý học, thương hiệu cũng được tác giả đề cập. Trong từng kỹ thuật, hầu hết đều có hình minh họa và giải thích nguyên nhân vì sao và cuối mỗi mục đều có phần tổng kết ngắn rất dễ hiểu và cụ thể, cứ làm theo ắt sẽ tăng tỷ lệ thành công.

Mỗi mục chỉ khoảng 2, 3 trang nên rất dễ đọc. Bên cạnh đó, mỗi phần liên quan đến nhau được gom theo từng nhóm màu sắc cho dễ phân loại như có các nhóm liên quan đến Icon, Form, Search…

Mình mua sách này ở Amazon và sách này là tiếng Anh, tuy nhiên, cách dùng từ và bố cục thông tin cực kỳ đơn giản, ngắn gọn và dễ hiểu. Bên dưới là danh sách 101 bài học theo như mục lục của sách, tuy nhiên, phần hấp dẫn nhất vẫn là đọc chi tiết bên trong do tác giả giải thích và mình họa, nên khuyến khích các bạn mua sách để tìm hiểu thêm và ủng hộ tác giả.

“Too many products labor the point: telling their users about their mission or vision, which is about how they’re trying to change the world. Please don’t do this because user simple don’t care. Products are useful for what they let users do. This pattern of too much information is a sympton of a lack of objectivity.” – trích #74. Users Don’t Care About Your Company, sách 100 UX Principles (Will Grant)

101 UX Principles

#1. Anyone Can Be a User Experience (UX) Professional

#2. Don’t Use More Than Two Typefaces

#3. Users Already Have Fonts on Their Computers, So Use Them

#4. USE TYPE SIZE TO DEPICT INFORMATION HIERARCHY

#5. Use a Sensible Default Size for Body Copy

#6. Use an Ellipsis to Indicate That There’s a Further Step

#7. Make Your Buttons Look Like Buttons

#8. Make Buttons a Sensible Size and Group Them Together by Function

#9. Make the Whole Button Clickable, Not Just the Text

#10. Don’t Invent New, Arbitrary Controls

#11. Search Should be a Text Field with a Button Labeled “Search”

#12. Sliders Should Be Used Only for Non-Quantifiable Values

#13. Use Numeric Entry Fields for Precise Integers

#14. Don’t Use a Drop-Down Menu If You Only Have a Few Options

#15. Allow Users to Undo Destructive Actions

#16. Think About What’s Just off the Screen

#17. Use “Infinite Scroll” for Feed–Style Content Only

#18. If Your Content Has a Beginning, Middle, and End, Use Pagination

#19. If You Must Use Infinite Scroll, Store the User’s Position and Return to It

#20. Make “Blank Slates” More Than Just Empty Views

#21. Make “Getting Started” Tips Easily Dismissable

#22. When a User Refreshes a Feed, Move Them to the Last Unread Item

#23. Don’t Hide Items Away in a “Hamburger” Menu

#24. Make Your Links Look Like Links

#25. Split Menu Items Down into Subsections, so Users Don’t Have to Remember Large Lists

#26. Hide “Advanced” Settings From Most Users

#27. Repeat Menu Items in the Footer or Lower Down in the View

#28. Use Consistent Icons Across the Product

#29. Don’t Use Obsolete Icons

#30. Don’t Try to Depict a New Idea With an Existing Icon

#31. Never Use Text on Icons

#32. Always Give Icons a Text Label

#33. Emoji are the Most Recognized Icon Set on Earth

#34. Use Device-Native Input Features Where Possible

#35. Obfuscate Passwords in Fields, but Provide a “Show Password” Toggle

#36. Always Allow the User to Paste into Password Fields

#37. Don’t Attempt to Validate Email Addresses

#38. Don’t Ever Clear User-Entered Data Unless Specifically Asked To

#39. Pick a Sensible Size for Multiline Input Fields

#40. Don’t Ever Make Your UI Move While a User is Trying to Use It

#41. Use the Same Date Picker Controls Consistently

#42. Pre-fill the Username in “Forgot Password” Fields

#43. Be Case-Insensitive

#44. If a Good Form Experience Can Be Delivered, Your Users will Love Your Product

#45. Validate Data Entry as Soon as Possible

#46. If the Form Fails Validation, Show the User Which Field Needs Their Attention

#47. Be Forgiving – Users Don’t Know (and Don’t Care) How You Need the Data

#48. Pick the Right Control for the Job

#49. Allow Users to Enter Phone Numbers However They Wish

#50. Use Drop Downs Sensibly for Date Entry

#51. Capture the Bare Minimum When Requesting Payment Card Details

#52. Make it Easy for Users to Enter Postal or ZIP Codes

#53. Don’t Add Decimal Places to Currency Input

#54. Make it Painless for the User to Add Images

#55. Use a “Linear” Progress Bar if a Task will Take a Determinate Amount of Time

#56. Show a “Spinner” if the Task Will Take an Indeterminate Amount of Time

#57. Never Show an Animated, Looping Progress Bar

#58. Show a Numeric Progress Indicator on the Progress Bar

#59. Contrast Ratios Are Your Friends

#60. If You Must Use “Flat Design” then Add Some Visual Affordances to Controls

#61. Avoid Ambiguous Symbols

#62. Make Links Make Sense Out of Context

#63. Add “Skip to Content” Links Above the Header and Navigation

#64. Don’t Only Use Color to Convey Information

#65. If You Turn Off Device Zoom with a Meta Tag, You’re Evil

#66. Give Navigation Elements a Logical Tab Order

#67. Write Clear Labels for Controls

#68. Let Users Turn off Specific Notifications

#69. Make Tappable Areas Finger-Sized

#70. A User’s Journey Should Have a Beginning, Middle, and End

#71. The User Should Always Know at What Stage They Are in Any Given Journey

#72. Use Breadcrumb Navigation

#73. If the User is on an Optional Journey, Give Them a Control to “Skip This”

#74. Users Don’t Care About Your Company

#75. Follow the Standard E-Commerce Pattern

#76. Show an Indicator in the Title Bar if the User’s Work is Unsaved

#77. Don’t Nag Your Users into Rating Your App

#78. Don’t Use a Vanity Splash Screen

#79. Make Your Favicon Distinctive

#80. Add a “Create from Existing” Flow

#81. Make it Easy for Users to Pay You

#82. Categorize Search Results into Sections

#83. Your Users Probably Don’t Understand the File System

#84. Show, Don’t Tell

#85. Be Consistent with Terminology

#86. Use “Sign in” and “Sign out”, Not “Log in” and “Log out”

#87. “Sign up” Makes More Sense Than “Register”

#88. Use “Forgot Password” or “Forgotten Your Password”, Not Something Obscure

#89. Write Like a Human Being

#90. Choose Active Verbs over Passive

#91. Search Results Pages Should Show the Most Relevant Result at the Top of the Page

#92. Pick Good Defaults

#93. Don’t Confound Users’ Expectations

#94. Reduce the Number of Tasks a User Has to Complete by Using Sensible Defaults

#95. Build Upon Established Metaphors – It’s Not Stealing

#96. Decide Whether an Interaction Should Be Obvious, Easy, or Possible

#97. “Does it Work on Mobile?” is Obsolete

#98. Messaging is a Solved Problem

#99. Brands Are Bullshit

#100. Don’t Join the Dark Side

#101. Test with Real Users

102. Bonus – Strive for Simplicity

Hy vọng sau khi đọc sách này thì các bạn sẽ yêu thích tìm hiểu hơn về mảng UI/UX và ngày càng tạo ra nhiều sản phẩm “chất” để người dùng trải nghiệm.