Tìm hiểu cách hoạt động, thách thức khi xây dựng Google Photos nền web

8
1019

Bài dịch còn nhiều sạn và theo sự hiểu biết ngôn từ hạn hẹp của mềnh, có thêm thắt và bỏ bớt 1 vài câu với mục đích giúp người đọc dễ hiểu hơn mà không bị mất thông tin. Mình rất hoan nghênh việc anh em góp ý cũng như đóng góp (thậm chí là request 1 bản dịch mới toanh cho những phần tiếp). Mình sẵn lòng thay đổi để giúp người đọc dễ nắm bắt thông tin cũng như học hỏi được trong bài mình viết chứ không phải là…. đọc cho vui rồi thôi.

Lưu ý: bài viết đang được hoàn thiện dần, các bạn có thể đóng góp bằng cách comment bên dưới.

Link bài viết gốc: https://medium.com/google-design/google-photos-45b714dfbed1

Nói sơ 1 chút: bài viết thực sự là 1 trend hiếm trên Medium, mình rất hay xem Medium, những bài trong mục Technology thường phải mất 1 thời gian dài và lượt view khoảng 15 triệu với 1 khoảng thời gian 1-4 tháng đã rất đáng đọc rồi. Bài viết này mình mới đọc qua 1 lần thôi – phải nói là rất nhiều thứ để học, những khái niệm mới, cách tiếp cận mới, cách hoạt động của 1 hệ thống lớn,…. Được viết bởi Antin Harasymiv – kỹ sư UX tài năng tại Google với chuyên môn chính là phát triển giao diện người dùng. Bài viết này mới publish ngày 10/7 nhưng đã nhanh chóng thu về những con số biết nói: 27 triệu lượt xem và 21k claps (gần như like nhưng khác ở chỗ mỗi người được claps tận 50 cái). Thôi, éo nói nhiều, cùng mình khám phá bài viết này bên dưới nhé!

Ngày nay, Google Photos đã trở thành 1 trong những ứng dụng được sử dụng nhiều nhất trên mọi nền tảng mà hầu hết mọi người đều cài đặt trên điện thoại thông minh, trong đó có mềnh — (y).

So deep….. Trở lại vài năm trước, tôi may mắn trở thành kỹ sư trong nhóm phát triển Google Photos khi phát hành lần đầu năm 2015. Rất nhiều con người tài năng trong nhiều lĩnh vực đã đóng góp để có được Google Photos như ngày hôm nay – từ designer, product managers, các nhà nghiên cứu và vô số kỹ sư (từ Android, iOS, Web và server). Trách nhiệm của tôi là phát triển giao diện người dùng (UI) phiên bản Web hay nói cụ thể hơn là chức năng Photo Grid.

Thật ngạc nhiên khi đây là Google, và chúng tôi luôn muốn thử 1 cái gì đó đầy tham vọng:

– Hỗ trợ bố cục hiển thị đầy đủ – nhưng phải hợp lý.
– Giữ đúng tỉ lệ khung hình của từng ảnh.
– Xử lý hàng trăm ngàn tấm ảnh.
– Đảm bảo tốc độ cuộn ở 60 khung hình/giây và tốc độ load gần như tức thì.

Vào thời điểm đó, không có thư viện nào hỗ trợ điều này, và theo sự hiểu biết của tôi, họ sẽ không làm bởi điều này quá tham vọng. Mặc dù nhiều thư viện ảnh khác có thể hỗ trợ 1 trong số những tính năng bên trên nhưng hầu như những thư viện này phải hiển thị tỉ lệ hình vuông để bố cục hiển thị hợp lý. Nhưng để có 1 sản phẩm tốt, chúng tôi cần giữ đúng tỉ lệ khung hình bởi người dùng sẽ không thích tấm ảnh của mình bị che mất vì bất cứ lý do nào.

Đây là bài viết kỹ thuật nói về cách mà chúng tôi giải quyết những thách thức đó. Qua đó sẽ cho bạn 1 cái nhìn rõ hơn về cách mà Google Photos phiên bản web hoạt động cũng như được xây dựng.

Tại sao điều này là 1 thách thức?

Thực tế có 2 thách thức to bự mà tôi phải đối mặt, chuẩn là to bự theo nghĩa đen luôn.

Thách thức đầu tiên: với người dùng có thư viện ảnh lớn (cá biệt 1 vài người dùng có hơn 1 triệu ảnh), trở về bài toán quá nhiều siêu dữ liệu. Cứ hình dung Google có hàng tỷ khách hàng, mỗi khách hàng có hàng trăm ngàn tấm ảnh. Để gửi những thông tin nhỏ nhất (url ảnh, chiều rộng, chiều cao và thời gian ảnh được tạo) phải tiêu tốn nhiều dữ liệu cho hàng tấn ảnh của mỗi người dùng. Điều này đi ngược với mục tiêu ban đầu của chúng tôi: mọi thứ cần được tải gần như ngay lập tức.

Thách thức to bự thứ 2 nằm ở chính những bức ảnh. Với màn hình HDPI hiện đại, ngay cả 1 tấm ảnh thu nhỏ thumbnail cũng đã ngốn 50KB trở lên. Một ngàn hình thu nhỏ cỡ 50MB và không phải chỉ 1000, còn rất nhiều, rất nhiều… Nếu bạn cố gắng tải tất cả chúng trong trang web ngay lập tức, chẳng khác nào bạn đang nghĩ trình duyệt của bạn là siêu nhân gao. Khi cuộn qua khoảng 100-2000 tấm ảnh, Chrome sẽ trở nên chậm chạp và nó mau chóng crash tab sau khi tải khoảng 10.000 tấm ảnh.

Giờ chúng ta cùng ngồi lại và chia nhỏ vấn đề ra thành nhiều mục khác nhau:

  1. Scrubbable Photos – 1 thuật ngữ được đội ngũ chúng tôi gọi vui. Bạn cứ nghĩ thư viện ảnh người dùng là 1 dòng thời gian, họ muốn du hành qua các mốc thời gian. Thì đây chính là bệ phóng tên lửa giúp người dùng có thể đi đến bất kỳ mốc thời gian nào của thư viện ảnh trong tích tắc.
  2. Bố cục hợp lý – vừa với chiều rộng của trình duyệt và giữ nguyên tỉ lệ khung hình của mỗi ảnh (tức không crop ảnh thành hình vuông).
  3. Tốc độ cuộn 60fps – đảm bảo trang web vẫn mau lẹ, không lag ngay cả khi xem hàng ngàn bức ảnh.
  4. Ngay lập tức – thời gian là vàng là bạc, không để người dùng chờ đợi bất cứ thứ gì để tải.

I. Scrubbable Photos:

Thực ra có 1 vài cách tiếp cận vấn đề này để giải quyết với thư viện ảnh lớn. Cách cũ nhất là phân trang, cho phép bạn hiển thị số lượng kết quả cố định và nhấp vào nút “Next” để xem loạt ảnh tiếp theo… à mà thôi bỏ đi. Cách tiếp cận hiện đại hơn, phổ biến hơn là cuộn vô hạn, như tên gọi, bạn có thể cuộn gần như vô hạn bởi khi cuộn đến số lượng kết quả được chỉ định, nó sẽ tự đồng tìm nạp lô ảnh tiếp theo và tự động thêm vào ứng dụng. Cứ thế, em nó sẽ tự động chèn lô ảnh mới mỗi khi người dùng cuộn xuống, nếu làm tốt thì người dùng có thể cuộn liên tục (gần như vô hạn) giúp tăng trải nghiệm người dùng rất cao.

Cả phân trang và cuộn vô hạn đều có nhược điểm giống nhau ở chỗ: bạn cần tải tất cả nội dung trước khi người dùng lướt trang web để xem. Điều gì sẽ xảy ra khi người dùng cần xem những bức ảnh từ nhiều năm trước, họ cuộn xuống dưới, chờ… chờ…. đến khi hiện ra những tấm ảnh 2013 họ đã đi ngủ cmnr.

Với 1 số tài liệu thông thường về thanh cuộn, bạn vẫn có cách để cuộn thanh cuộn nhanh hơn giúp bỏ qua các thời điểm để chuyển thằng tới cuối hoặc đến bất kỳ thời điểm nào khác. Với phân trang, thanh cuộn sẽ chạm tới cuối trang. Đối với cuộn vô hạn, thanh cuộn luôn thay đổi, nếu bạn kéo xuống cuối, bạn sẽ thấy nó cuộn lại 1 chút (vì nó load tiếp nội dung).

A scrubbable photo grid presents a third option, one where the scrollbar behaves properly – nguyên văn. Mình không biết dịch như thế nào cho chuẩn.

Scrubbable photo sẽ giúp người dùng du hành đến bất cứ mốc thời gian nào trong thư viện ảnh của họ, do đó chúng tôi cần pre-allocate – phân bố trước không gian trên trang để khi người dùng cuộn thanh cuộn sẽ hiển thị các mốc, ở mỗi mốc sẽ chứa những tấm ảnh thuộc về mốc thời gian đó. Điều này tương đối dễ dàng nếu chúng tôi có thông tin cho tất cả bức ảnh (biết thời gian sẽ tạo được mốc) nhưng vì có quá nhiều ảnh xử lý phía client nên chúng tôi phải làm 1 cách khác thôi.

Một lối tắt nhanh chóng được mở ra – chúng tôi đã thực hiện crop từng tấm ảnh của người dùng thành những hình vuông giống hệt nhau. Bằng cách này, bạn chỉ cần biết tổng số ảnh để tính toán toàn bộ bố cục trang, tức là: cho 1 kích thước hình vuông nhất định, bạn có thể lấy chiều rộng của thiết bị (mỗi thiết bị có độ phân giải và tỉ lệ màn hình khác nhau, ta dùng thuộc tính viewportWidth để lấy chiều rộng) và sử dụng nó để tính số cột và hàng:

Chỉ với 3 dòng mã, việc tính toán chiều rộng cũng như chiều cao đã hoàn tất cho phép bạn tính toán để hiển thị và định vị các bức ảnh trên mỗi màn hình khác nhau.

Cách tiếp cận mà chúng tôi đưa ra để giảm kích thước ban đầu của tệp siêu dữ liệu là chia nhỏ toàn bộ ảnh của người dùng thành các section. Ở lần tải đầu tiên sẽ gửi các section và số lượng của chúng. Ví dụ: 1 cách đơn giản để tạo ra các vùng thời gian theo tháng – bạn có thể đếm chúng trên máy chủ (hoặc tính toán trước), bởi mọi việc đều xử lý trên máy chủ của Google nên hàng triệu, thậm chí hàng tỷ bức ảnh trải dài hàng thập kỷ chỉ là 1 lượng dữ liệu nhỏ. Dữ liệu được chia ra thành nhiều vùng trông như thế này:

Trong trường hợp đặc biệt, điều này vẫn có thể có vấn đề với người dùng chụp rất nhiều ảnh trong 1 tháng nhất định (thường là nhiếp ảnh gia chuyên nghiệp) – mục tiêu khi phân ra từng vùng thời gian là giảm lượng siêu dữ liệu xuống mức có thể quản lý được. May mắn là nhóm hạ tầng thông minh tại Google đã xuất sắc vượt qua bản thân và xây dựng 1 giải pháp tinh vi, sắp xếp mọi thứ vào từng tài khoản (như: vị trí địa lý, thời gian gần đúng của bức ảnh,…) tạo ra các section được tùy biến riêng cho từng người dùng một.

Với thông tin đó, trình duyệt của người dùng có thể ước lượng khoảng trống mà mỗi section cần và đặt chính xác vào DOM. Khi người dùng cuộn nhanh đến từng section, nó sẽ truy xuất siêu dữ liệu tương ứng đã được xử lý bởi máy chủ Google, tính toán bố cục hợp lý và cập nhật lại trang.

Lúc này trên máy client, chúng tôi đã có tệp siêu dữ liệu của section, chúng tôi đã tiến gần hơn 1 bước nữa với việc phân bố những segment ảnh trong mỗi section vào từng ngày cụ thể. Chúng tôi đã bàn đến việc phân ra nhiều segment khác như: theo địa điểm, theo ngày,… đây sẽ là bàn đạp để phát triển thêm 1 tính năng mới trong tương lai.

Nói 1 chút về section và kích thước section: như tác giả nói – section là 1 không gian chứa rất nhiều tấm ảnh của mỗi người dùng. Khi người dùng cuộn trang, sẽ tạo ra từng mốc thời gian (section), mỗi mốc thời gian sẽ được đánh dấu bởi nhiều segment. Khi người dùng lướt ngón tay tới từng mốc, Google sẽ tính toán thuộc tính thời gian và hiển thị chính xác những bức ảnh trong section đó. Vì mỗi section là tập hợp nhiều ảnh, có thắng nhiều, tháng ít nên kích thước section là chiều rộng và chiều cao của section đó.

Việc ước tính kích thước section hóa ra dễ dàng hơn rất nhiều, bạn chỉ cần tính số lượng ảnh cho 1 section và nhân với tỷ lệ khung ảnh thông thường:

Ban đầu tôi đã nghĩ vấn đề này khá phức tạp (tôi sẽ giải thích ở phần “Bố cục”) nhưng hóa ra cái estimate không nhất thiết quá chính xác. Điều quan trọng là ước tính gần đúng sao cho khi người dùng cuộn thanh cuộn, nó trông có vẻ cuộn tới mốc thời gian chính xác nhưng thực tế là gần đúng để xác định vị trí của thanh cuộn.

Bí quyết đơn giản là khi bạn load section cuối, tính toán sai lệch giữa chiều cao ước lượng và chiều cao thực của 1 section. Nếu có sai lệch, thì section bên dưới sẽ được tự động cập nhật 1 lượng sai lệch y như vậy để đảm bảo vị trí của scroll không bị sai.

Nếu 1 section có độ dài lớn hơn khả năng hiển thị của thanh scroll (thanh cuộn) trong màn hình thì chúng ta cần cập nhật lại vị trí thanh scroll cho chính xác. Tuy nhiên việc cập nhật vị trí thanh scroll này đơn giản và nhanh chóng trong 1 frame chuyển cảnh mượt mà. Vậy nên người dùng không thể nhận biết sự thay đổi này.

Chào anh em, mình đã dịch xong phần 1, phần 2, 3, 4 có rất nhiều điều cực kỳ thú vị đang chờ các bạn.

Bởi mình chỉ dịch 1 đoạn cho anh em xem để kích thích anh em thèm đọc. Giả như anh em thấy hay thì tự mò bản Eng- mình có post link đầu bài mà đọc chứ mình không đủ sức để dịch hết bởi khả năng của mình có hạn. :v 1 phần nữa là rút kinh nghiệm 2 bài trước, mình dịch dài vl mà ếu có người đọc nên thay vì dịch full mình sẽ dịch 1 phần và kích thích sự tò mò của anh em.

Link 2 bài viết bị anh em kỳ thị, anh em nào chưa đọc thì xem và để lại comment cho mình “đỡ tủi” nhé:

I: Xây dựng web app thời tiết đẹp với Angular 6 từ A đến Z – Thiết kế.

II: Xây dựng web app thời tiết đẹp với Angular 6 từ A đến Z – Implement Code.

Cảm ơn các bạn đã xem bài viết. Hãy COMMENT điều gì đó để khích lệ cũng như phê bình văn học. Để mình vui hoặc mình tiếp nhận để cố gắng hơn vào lần sau.

Lưu ý: anh em comment thoải mái. Đừng chửi mềnh là được vì mình không làm gì khiến anh em muộn phiền.

À, thánh nào copy bài viết thì để link tới nguồn bài viết. Nếu mình phát hiện thanh niên nào copy không để lại nguồn thì…. đậu xanh đậu đỏ bạn nhé!

 

Tìm hiểu cách hoạt động, thách thức khi xây dựng Google Photos nền web
4.8 (95.56%) 18 votes

8
Bình luận bài viết

avatar
4 Comment threads
4 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
5 Comment authors
Lê Đức ThọPeter Samcuong nguyenBà NaLinh IT Recent comment authors
mới nhất cũ nhất like nhiều nhất
Lê Đức Thọ | <span class="wpdiscuz-comment-count">3 comments</span>
Khách
Lê Đức Thọ | 3 comments

Rất hóng phần 2 3 4 5. Bài viết giới thiệu hay quá. Cảm ơn Admin nhiều ạ ♥

Peter Sam | <span class="wpdiscuz-comment-count">13 comments</span>
Khách
Peter Sam | 13 comments

Rối Não Quá , ai kiếm lại giùm tui coi ~~

cuong nguyen | <span class="wpdiscuz-comment-count">3 comments</span>
Khách
cuong nguyen | 3 comments

mình chưa biết gì về mấy cái của ngành CNTT này, muốn đọc hiểu mà ko hiểu đc :(, ai ơi mình muốn hiểu đc bài viết thì nên bắt đầu từ đâu đây 🙂

Linh IT | <span class="wpdiscuz-comment-count">10 comments</span>
Khách
Linh IT | 10 comments

Đúng là bài toán phải tính toán thật.