Blog

  • Web Architecture?

    Web Architecture?

    Bài này thực ra là đi copy từ đây, nhưng dịch lại theo ngôn ngữ dễ hiểu thôi : ).

    Web hiện tại thì nó như thế này : )

    Trông có vẻ phức tạp nhưng gần như mình sử dụng hết các phần trong này đó. Thông thường thì mình không để ý đến 9a và 9c, 10 cũng khá optional nhưng thôi cứ đề cập cả.

    Câu chuyện ở trong bài viết hơi khác nhưng mình sẽ diễn giải lại thế này.

    Khi bạn tìm kiếm techover trên Google, kết quả đầu tiên tìm được sẽ là: https://magz.techover.io/. Khi ấn vào link đó, trình duyệt sẽ truy cập đến DNS server tìm kiếm cách truy cập đến magz.techover.io, sau đó trình duyệt sẽ gửi request. Request đầu tiên sẽ truy cập đến CDN Cloudfront của magz.techover.io, các request đã cache sẽ đựoc response luôn từ Edge Location của Cloudfront. Các request khác sẽ đến Load Balancer, và chọn ngẫu nhiên 1 trong 5 Server LightSail của techover. Webserver sẽ truy vấn vào database, tra cứu một số thông tin về các hình ảnh có trong bài viết từ S3 và thực hiện thay đổi database. Và tất nhiên giờ đây, Server sẽ luôn response cho người đọc chế độ xem dưới dạng HTML và gửi lại cho trình duyệt của người dùng, trước tiên chuyển qua bộ cân bằng tải. Trang này chứa các tài sản Javascript và CSS mà mấy cái này thì lại được cache ở CDN ở ban đầu ấy, vì vậy trình duyệt của người dùng liên hệ với CDN để lấy nội dung. Cuối cùng, trình duyệt hiển thị rõ ràng trang cho người dùng xem. Tiếp theo, khi người đọc tìm kiếm bài viết tương tự Server sẽ gửi yêu cầu đến Fulltext Search Service bằng cách sử dụng tiêu đề bài viết và các từ khóa có trong nội dung. Tương lai gần, dịch vụ này cũng phục vụ cho custom feed cho từng user một dựa trên các sở thích hay xu hướng tìm kiếm các từ khóa ở techover. Nhưng bây giờ mỗi khi người dùng đăng bài, chúng tôi sẽ lưu trữ tạm kết quả của trang home ở một Server cache Redis để phục vụ người dùng tốt hơn. Sau đó người dùng viết bài, các tác vụ upload ảnh, resize khá nặng vì vậy sẽ đẩy các công việc này vào queue SQS và được thực hiện bởi các worker, mà các worker này sẽ xử lý không đồng bộ, cập nhật database phù hợp với kết quả, các hình ảnh này sau khi được xử lý xong sẽ được lưu trữ trên S3 và có một CDN Cloudfront khác phục vụ request. Đấy là toàn bộ bức tranh của trang techover hiện tại, cũng khá đủ component.

    Tiếp theo thì mình sẽ đi qua từng cái ở trên kia, mấy cái khóa ở trường đại học thường sẽ dùng số 101 để cho các khóa introduction nên ông tác giả để như thế. Chắc sẽ có một vài series 102, 103 để nói rõ hơn.

    DNS

    Domain Name System, tên nó là thế. Gần như đây là một thứ cốt lõi trong thế giới Web hiện nay. Ở mức cơ bản nhất, DNS cung cấp tra cứu key-value từ một tên miền – domain (ví dụ: google.com) đến địa chỉ IP (ví dụ: 85.129.83.120), được yêu cầu để máy tính của bạn định tuyến(route) yêu cầu đến server phù hợp. Tương tự với số điện thoại, sự khác biệt giữa tên miền và địa chỉ IP là sự khác biệt giữa cuộc gọi của Nguyen Van A, và cuộc gọi 0945123456. Giống như bạn cần một cuốn sách điện thoại để tra cứu số của A trong những ngày xưa, bạn cần DNS để tra cứu địa chỉ IP cho một tên miền. Vì vậy, bạn có thể nghĩ DNS là danh bạ điện thoại cho internet. Có nhiều chi tiết khác chúng tôi có thể đi vào đây nhưng mình sẽ bỏ qua vì nó không quan trọng cho bài 101 này.

    Thực ra có một series khác nói về cái này rõ hơn, có thể tìm thấy ở đây này.

    Load Balancer

    Cân bằng tải, thực ra trong ví dụ của techover thì Load Balancer (LB) còn sau cả CDN nhưng nó không tiêu chuẩn và không hay dùng như thế lắm nên mình để ở đây.

    Hồi ở đại học thì mọi người sẽ biết đến khái niệm mở rộng theo chiều ngang (Horizontal scaling) và mở rộng theo chiều dọc (Vertical scaling). Thì mở rộng theo chiều dọc là nâng cấp phần cứng: Ram, CPU, Bandwidth, … cho Server làm cho Server mạnh hơn đúng nghĩa theo chiều dọc, còn mở rộng theo chiều ngang là thay vì bạn nâng cấp, bạn sẽ mua thêm Server mới, đặt ngang hàng với Server cũ, không tin thì xem ở Stackoverflow này.

    Lúc phát triển một ứng dụng web, thường thì mọi người sẽ thích mở rộng theo chiều ngang hơn vì nó đơn giản, chỉ cần cài thêm server là được. Các vấn đề bất ngờ như: Server sự cố, crash, mất điện datacenter bất ngờ, sự cố thiên tai, … có thể dễ dàng được phòng chống bằng cách đưa thêm Server, ngoài ra khi có nhiều Server chúng ta sẽ có thể bảo trì một trong các Server một cách dễ dàng mà không làm ảnh hưởng đến người dùng vì vẫn còn những Server khác hoạt động. Thuật ngữ thường dùng ở đây là fault tolerant. Thứ hai, việc mở rộng theo chiều ngang cho phép các component của ứng dụng không liên kết quá chặt chẽ với nhau (low coupling) (như Web Server, Database, Service, v.v.), bằng cách cho mỗi component chạy trên một cum Server khác nhau. Cuối cùng, lý do cốt lõi nhất, đồng ý bạn có thể mở rộng theo chiều dọc tuy nhiên đến một lúc nào đó bạn không để mở rộng được nữa,ví dụ như giới hạn của rack server, của datacenter, không có máy tính nào trên thế giới đủ lớn để thực hiện tất cả các tính toán ứng dụng của bạn, trong khi đó việc mở rộng theo chiều ngang gần như không hạn chế. Ví dụ thực tế như này, Netflix một lúc có thể chạy vài chục đến vài nghìn EC2 instance mỗi loại, thậm chí có dùng cả GCP và Azure, không có Server nào đủ lớn để chạy toàn bộ ứng dụng của Netflix trên một Server duy nhất cả.

    Lan man hơi nhiều, nhưng trở lại với Load Balancer, có thể nhận ra rằng Load Balancer lại là cái không thể thiếu để thực hiện mở rộng theo chiều ngang. LB định tuyến các request từ user/client đến các Server khác nhau và đưa kết quả về lại cho user/client, mấy cái Server này thường là các bản sao của một server gốc, hay đơn thuần chỉ là bạn cài đặt lại toàn bộ Server đó. Bất kỳ Server nào trong số đó cũng nên xử lý request theo cùng một cách để nó chỉ là vấn đề phân phối các request trên toàn bộ các Server để không Server nào bị quá tải.

    Đó, Load Balancer về mặt khái niệm là đúng theo nghĩa đen, tất nhiên đằng sau đó là một loạt các công nghệ khác nhau, nhưng cuối cùng vẫn phải đề cập ở một bài viết cụ thể hơn.

    Web Application Servers

    Ở high level, các Web Application Server tương đối đơn giản để mô tả. Những server này thực thi logic nghiệp vụ cốt lõi xử lý request của người dùng và gửi lại HTML cho trình duyệt của người dùng. Để thực hiện công việc của mình, các server này có kết nối với nhiều cơ sở hạ tầng phụ trợ như database, caching, queue job, searching service, các micro-service khác, logging, v.v. Như đã đề cập ở trên, mọi người thường có sử dụng 1 hoặc nhiều load balancer trong cùng một ứng dụng. Web App thì có thể sử dụng nhiều ngôn ngữ khác nhau (Node.js, Ruby, PHP, Scala, Java, C # .NET, v.v.) và một framework MVC cho ngôn ngữ đó (Express cho Node.js, Ruby on Rails , Play Framework cho Scala, Laravel cho PHP, v.v.). Tuy nhiên, đi sâu vào chi tiết của các ngôn ngữ và khung này nằm ngoài phạm vi của bài viết này.

    Database

    Hiện nay, mỗi Web Application thường sử dụng một hoặc nhiều database để lưu trữ thông tin. Database cung cấp các cách xác định cấu trúc dữ liệu của bạn, insert dữ liệu mới, search/select dữ liệu hiện có, update hoặc xóa dữ liệu hiện có, thực hiện tính toán trên dữ liệu và hơn thế nữa. Trong hầu hết các trường hợp, các Web Application Server, cũng như các Worker Server làm việc trực tiếp một Database. Ngoài ra, mỗi Backend có thể có cơ sở dữ liệu riêng của mình và riêng biệt với với phần còn lại.

    Trong bài viết nay, thường sẽ tránh nói sâu về một loại công nghệ cụ thể, thế nên chỉ đề cập đến 2 loại database: SQL và NoQuery.

    SQL là viết tắt của Structured Query Language, ngôn ngữ này cung cấp một cách truy vấn tiêu chuẩn cho các bộ dữ liệu quan hệ có thể truy cập được đối tượng. Cơ sở dữ liệu SQL lưu trữ dữ liệu trong các bảng được liên kết với nhau thông qua các quan kệ: Id, Foreign Id . Hãy xem qua một ví dụ đơn giản về lưu trữ thông tin địa chỉ lịch sử cho người dùng. Bạn có thể có hai bảng, useruser_addresses, được liên kết với nhau bởi id người dùng. Xem hình ảnh dưới đây cho một phiên bản đơn giản. Các bảng được liên kết bằng cột user_id trong user_addresses là một Foreign key, với cột id trong bảng user.

    Nếu bạn không biết nhiều về SQL, tôi khuyên bạn nên tìm hiểu hướng dẫn như bạn có thể tìm thấy ở W3School tại đây. SQL gần như xuất hiện ở mọi Web Application Server, nhìn chung gần như bạn không thể làm Web mà không biết gì về SQL cả. NoQuery, viết tắt của từ Non-SQL, là một công nghệ cơ sở dữ liệu mới hơn đã xuất hiện để xử lý lượng dữ liệu khổng lồ có thể tạo ra Web Application với quy mô lớn (hầu hết các biến thể của SQL không thể mở rộng theo chiều ngang quá tốt và chỉ có thể mở rộng theo chiều dọc đến một điểm nhất định). Nếu bạn không biết gì về NoQuery, mình khuyên nên bắt đầu với một số link dưới đây:

    I would also keep in mind that, by and large, the industry is aligning on SQL as an interface even for NoSQL databases so you really should learn SQL if you don’t know it. There’s almost no way to avoid it these days.

    Về cơ bản cũng sẽ ghi nhớ rằng, gần như tất cả phần mềm đang liên kết với SQL như một giao diện thường thấy ngay cả đối với NoSQL, họ cũng tạo ra các framework cũng như library để hỗ trợ truy vấn NoSQL như một database SQL thông thường, thế nên thực sự cần biết về SQL, kiểu gì bạn cũng gặp những thứ này thôi.

    Caching Service

    Caching Service cung cấp một một nơi lưu trữ theo kiểu key-value đơn giản, cho phép tra cứu các thông tin với độ phức tạp O(1). Các ứng dụng thường tận dụng các Caching Service để lưu kết quả của các tính toán nặng và khó để có thể lấy lại kết quả từ cache thay vì tính toán lại chúng vào lần tiếp theo khi chúng ta cần. Một ứng dụng có thể lưu trữ kết quả từ truy vấn database, kết quả gọi đến một API ở bên ngoài, HTML cho một URL nhất định và nhiều hơn nữa. Dưới đây là một số ví dụ từ các ứng dụng trong thế giới thực:

    • Google lưu trữ kết quả tìm kiếm cho các truy vấn tìm kiếm phổ biến như Taylor Swift hay World Cup, thay vì tính lại chúng mỗi lần
    • Facebook lưu trữ nhiều dữ liệu có thể hiển thị lúc bạn đăng nhập, chẳng hạn như dữ liệu bài đăng, bạn bè, v.v. À có một bài chi tiết về vụ Facebook ở đây

    Job Queue & Servers

    Hầu hết Web Appliaction cần thực hiện một số async job ở background mà không liên quan trực tiếp đến việc tiếp nhận và đáp ứng request của người dùng. Chẳng hạn, Google cần thu thập dữ liệu và lập chỉ mục toàn bộ internet để trả về kết quả tìm kiếm. Google không làm điều này mỗi khi bạn tìm kiếm. Thay vào đó, Google thu thập dữ liệu web không đồng bộ, cập nhật các chỉ mục tìm kiếm khi duyệt các trang web. Mặc dù có các kiến ​​trúc khác nhau cho phép thực hiện async job, nhưng phổ biến nhất là kiểu Queue hay Queue Job. Cài này bao gồm hai thành phần:

    • Một là queue, tất nhiên rồi, thường thì có thể dùng database queue, Redis queue, xịn xò hơn thì dùng dịch vụ cloud như SQS của AWS hay Task Queue ở GCP, Queue này lưu trữ một danh sách các async job. Đơn giản nhất là queue FIFO
    • Hai là cái thực hiện công việc trong queue, thường được gọi là Worker hay Job Server. Bất cứ khi nào Application cần chạy một job, theo một thứ tự thông thường hoặc được xác định bởi hành động của người dùng, thì Application sẽ thêm một job vào queue. Ví dụ, Techover sử dụng queue job làm nhiều background job cần thiết cho công việc. Techover dùng các job để resize ảnh, xử lý CSV để gắn tag, cập nhật Elastic Search index, gửi email đặt lại mật khẩu và nhiều cái nữa. Đầu tiên chúng tôi sử dụng một queue FIFO đơn giản sau đó nâng cấp lên hàng đợi ưu tiên để đảm bảo rằng các hoạt động cần kíp như gửi email đặt lại mật khẩu đã được hoàn thành càng sớm càng tốt. Worker Server, thông thường được cài đặt riêng hoặc có thể chạy cùng với Application Server cho tiết kiệm tài nguyên, các Server này kiểm tra queue job để xác định xem có job nào để làm hay không và nếu có, họ sẽ lấy job (pop) ra khỏi queue và thực hiện(execute). Chi tiết về vụ ngôn ngữ và framework thì lại không đề cập ở bài viết này nhé.

    Full-text Search Service

    Nhiều Web Application, nếu không phải hầu hết đều hỗ trợ một số tính năng tìm kiếm trong đó người dùng nhập vào một đoạn keyword(query) và Web Application trả về kết quả có liên quan nhất về keyword đó. Công nghệ dùng cho chức năng này thường được gọi là Full-text Search, trong đó sử dụng một inverted index để nhanh chóng tra cứu các tài liệu có chứa các từ khóa truy vấn.

    Ví dụ cho thấy cách ba title của document được chuyển đổi thành một inverted index để tạo điều kiện tra cứu nhanh từ một từ khóa cụ thể đến các document có từ khóa đó trong title. Lưu ý, các từ phổ biến như trên mạng, trong đó có các từ phổ biến, như “in”, “the”, “with” (Stop word), thường không được đặt trong một inverted index.

    Mặc dù nó có thể thực hiện Full-text Search trực tiếp từ một số cơ sở dữ liệu (ví dụ: MySQL hỗ trợ Full-text Search), nhưng chúng ta có thể sử dụng một Search Service riêng biệt, tính toán và lưu trữ inverted index và cung cấp query interface. Full-text Search Platform nổi tiếng và phổ biến nhất hiện tại là Elaticsearch mặc dù có các tùy chọn khác như Sphinx hoặc Apache Solr.

    Services

    Khi một Application đạt đến một quy mô nhất định, có khả năng sẽ có một số Service nhất định được refactor để chạy như các Application riêng biệt. Những service này không tiếp xúc với thế giới bên ngoài nhưng sẽ tương tác cùng Application và các service khác. Ví dụ như Techover, có một số service hoạt động và theo schedule:

    • Service gửi mail
    • Service chạy hằng đêm để đồng bộ tài khoản
    • Service export file thành PDF

    Data

    Ngày nay, các công ty sống dựa vào người dùng và dữ liệu. Hầu như mọi ứng dụng ngày nay, một khi nó đạt đến một quy mô nhất định, tận dụng một data pipeline để đảm bảo rằng data có thể được thu thập, lưu trữ và phân tích. Một data pipeline điển hình có ba giai đoạn chính:

    1. Ứng dụng sẽ gửi data, điển hình là các sự kiện về tương tác của người dùng, đến data Firehose, nơi cung cấp các interface dùng để nhập và xử lý data. Thông thường, data thô được chuyển đổi hoặc xử lý thêm data và chuyển sang một Firehose khác. AWS Kinesis (bao gồm cả Kinesis Data Firehose)và Kafka là hai công nghệ phổ biến nhất cho mục đích này.
    2. Data thô cũng như data được chuyển đổi cuối cùng được lưu vào Cloud Storage. AWS Kinesis cung cấp một cài đặt Firehose, giúp lưu trữ data thô vào Cloud Storage S3.
    3. Data được chuyển đổi cũng thường được lưu vào một loại database để phân tích – Data Warehouse, cũng không phải là loại database dùng cho Application thường thấy. Ở AWS thường chúng ta sẽ dùng AWS Redshift, đây là một sản phẩm ưa chuộng của giới ít tiền nhất là các startup, bên cạnh đó các công ty lớn hơn sẽ thường sử dụng Oracle hoặc các Data Warehouse. Nếu các bộ dữ liệu đủ lớn, các Hadoop-like NoSQL như MapReduce có thể dùng để phân tích dữ liệu. Một bước cuối cùng mà thường không được hình dung trong sơ đồ kiến ​​trúc: Load data từ Application vào dịch vụ Data Warehouse. Ví dụ: tại một số trang web sẽ chuyển data từ một OLTP Database vào Redshift mỗi đêm. Việc này giúp cho các data scientist có toàn bộ dữ liệu đầy đủ nhất để phân tích và đưa ra các quyết định.

    Cloud storage

    Theo AWS: "Cloud storage là một phương thức đơn giản và có thể mở rộng để lưu trữ, truy cập và chia sẻ dữ liệu qua Internet". Bạn có thể sử dụng nó để lưu trữ và truy cập bất cứ thứ gì như khi bạn lưu trữ trên hệ thông localfile với thêm lợi ích là có thể tương tác với nó thông qua API RESTful qua HTTP. Amazon S3 cho đến nay vẫn là bộ lưu trữ đám mây tuyệt vời nhất hiện nay và là nơi Techover dùng để lưu trữ video, ảnh và âm thanh, CSS và Javascript, dữ liệu người dùng(tất nhiên là private bucket) và nhiều cái khác nữa.

    CDN – Content Delivery Network

    CDN cung cấp cách transfer các file như HTML tĩnh, CSS, Javascript và hình ảnh trên web nhanh hơn nhiều so với lấy chúng từ một Server nào đó. Nó hoạt động bằng cách distribute các content trên nhiều máy chủ (Edge Location) trên toàn thế giới, để enduser có thể tải xuống các file này từ đó thay vì máy chủ gốc. Ví dụ trong hình ảnh bên dưới, một người dùng ở Tây Ban Nha yêu cầu một trang web từ một trang web có Origin Server ở New York, nhưng các file tĩnh cho trang được tải từ Server Edge CDN, ở Anh, ở Pháp, điều này giúp người dùng tải trang nhanh hơn trải nghiệm mượt mà hơn.

    Về vụ CDN thì có thể xem thêm ở bài viết này.

    EOF

    Cũng hết những cái đề cập từ đầu rồi, bài viết này với mục đích 101 để mọi người hình dung rõ hơn về thế giới web :).

  • Authorization and JWT

    Authorization and JWT

    Thực ra bài này chỉ muốn viết về JWT thôi, nhưng tiện thì sẽ nói về các loại Authorization luôn.

    Authorization và Authentication

    2 cái này cũng khác nhau:

    • Authentication
      • Được sử dụng bởi một Server khi mcần biết chính xác ai đang truy cập thông tin hoặc trang web của họ.
      • Được sử dụng bởi Client khi Client cần biết rằng máy chủ là hệ thống mà nó tuyên bố.
      • Trong Authentication, Client hoặc Machine phải chứng minh danh tính của mình với Server hoặc Client. Thông thường, xác thực bởi một máy chủ đòi hỏi phải sử dụng tên người dùng và mật khẩu. Các cách khác để xác thực có thể thông qua thẻ, quét võng mạc, nhận dạng giọng nói và dấu vân tay. Xác thực bởi khách hàng thường liên quan đến việc máy chủ cấp chứng chỉ cho khách hàng trong đó một bên thứ ba đáng tin cậy như Verisign hoặc Thawte nói rằng máy chủ đó thuộc về thực thể (như ngân hàng) mà khách hàng mong đợi. Xác thực không xác định những nhiệm vụ mà cá nhân có thể làm hoặc những tập tin cá nhân có thể nhìn thấy. Xác thực chỉ xác định và xác minh người hoặc hệ thống là ai.

    Xác thực, quá trình này xác định bạn là ai trong hệ thống. Ví dụ: login là một quá tình xác thực, bạn gửi username/password lên hệ thống, hệ thống sẽ thẩm tra nhận dạng của bạn (bằng username/password hoặc thêm một số factor nữa như trắc sinh học, token,… trong multi-factor authentication).

    • Authorization
      • Xác minh, cái này thường sau xác thực, để kiểm tra xem bạn có quyền truy cập tài nguyên không, ví dụ bạn nói với server tôi là A tôi cần truy cập tài nguyên B bằng một request:
      GET /b HTTP/1.1
      Host: example.com
      Authorization: Bearer i_am_A
      
      Như vậy server cần xác định Bearer i_am_A có phải là Authorization hợp lệ hay không và có quyền truy cập GET /b hay không.
      • Gần như 2 quá trình trên sẽ không khác nhau với các website hay application, vì vậy việc hiểu rõ khá là hữu ích.
      • Authorization cũng thường lấy kết quả của Authentication (hoặc một dẫn xuất từ việc Authentication) để xác nhận. Ví dụ sau khi đăng nhập bạn sẽ được Server gán cho một giá trị nào đó vào Session để xác nhận bạn đã đăng nhập, và dùng giá trị đó cho việc Authorization. Có một vài trường hợp khác như Basic Authentication bạn sẽ gửi Base64 của chuỗi username:password trong Authorization header, thì gần như sẽ ko thấy Authentication đâu cả.

    Vì vậy cũng có vài loại Authorization khác nhau:

    • Basic (RFC 7617, base64-encoded credentials. Đơn giản là truyền chuỗi Base64 của chuỗi username:password)
    • Bearer (RFC 6750, bearer tokens để access các resource được bảo vệ bởi OAuth 2.0)
    • Digest (RFC 7616)
    • HOBA (RFC 7486, HTTP Origin-Bound Authentication, digital-signature-based),
    • Mutual (RFC 8120,
    • AWS4-HMAC-SHA256 dùng cho AWS SDK và AWS API.

    Hiện tại thì OAuth 2.0 rất phổ biến hơn nữa nảy sinh ra nhu cầu chống làm giả token được tạo ra bởi server, đến đây thì mới xuất hiện JWT.

    JWT

    Thôi đi copy định nghĩa vậy: JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties. JWT.IO allows you to decode, verify and generate JWT.

    Hình dung như này, khi bạn vào một trang web như TIKI chẳng hạn, bạn đăng nhập với Facebook hoặc tài khoản cá nhân. Vậy khi bạn đăng nhập với Facebook, TIKI sẽ kết nối đến Facebook GraphAPI với Facebook token mà bạn vừa đưa cho TIKI để verify. Khi đó bạn sẽ nhận được token từ TIKI để truy cập các resource.

    Structure

    JWT gồm 3 phần:

    • Header: Hay còn gọi là JOSE header, đề cập đến loại JWT (JWEJWS)và kiểu mã hóa hay thuật toán mã hóa, ở hình trên là dùng RSA Signature with SHA-256
    • Payload: hay còn gọi là claims, là một đoạn data public có trong JWT, JWT thường có một vài data có thể public như
      • sub: Username hoặc UserId
      • iat: issue at, token được tạo ra lúc nào
      • exp: expire at, token hết hạn khi nào
      • iss: issuer, ai là người tạo token này ra. Ngoài ra còn có jti(JWT ID), aud(Audience), nbf(Not before), mấy cái tên này thì có thể tìm thấy ở đây này, cái này được gọi là Public Claims. Private Claims thì những cái bạn define thôi : ).
    • Signature: là phần quan trọng nhất, thì cái này lại phụ thuộc vào JOSE Header để mã hóa, tức là dùng cái thuật toán ở trên ấy, mã hóa dùng security factor như nào thì lại phụ thuộc vào JWE hay JWS.

    Xong xuôi, chúng ta sẽ dùng process base64url encode cả 3 phần rồi nối với nhau bằng dấu chấm (.).

    JWT vs Thế giới

    So với các web token khác như SWT hoặc SAML, JWT đơn giản hơn nhiều vì nó dựa trên JSON nên dễ hiểu hơn XML. Nếu chúng ta mã hóa JSON, nó sẽ trở nên nhỏ hơn kích thước so với SAML, giúp việc chuyển qua môi trường HTML và HTTP dễ dàng hơn. Về bảo mật, SWT sử dụng một khóa duy nhất, trong khi cả JWT và SAML đều sử dụng cặp khóa chung và khóa riêng để xác thực tốt hơn. Nhìn chung, JWT được sử dụng ở quy mô Internet. Điều này có nghĩa là việc xử lý trên các thiết bị của người dùng dễ dàng hơn, có thể là máy tính xách tay hoặc thiết bị di động. Ngoài khả năng tự động hóa, Mã thông báo Web JSON là một cách tuyệt vời và an toàn để truyền dữ liệu giữa nhiều bên. Việc JWT có chữ ký giúp mọi người dễ dàng xác định người gửi thông tin hơn. Tất cả bạn cần là chìa khóa chính xác.

    Một bài viết khác sẽ nói về một loại JWT của Auth0. Hãy đón chờ : )

  • Tối ưu Nginx & PHP-fpm cho lượng truy cập lớn

    Tối ưu Nginx & PHP-fpm cho lượng truy cập lớn

    PHP hiện tại là ngôn ngữ được triển khai rộng rãi trên Internet.

    Tuy nhiên PHP lại hay được nhìn nhận là 1 ngôn ngữ có khả năng hiệu suất (performance) kém, do đó khi các website, api có lượng truy cập lớn lại nghĩ tới sử dụng các ngôn ngữ khác như Nodejs, Golang…

    Mặc dù vậy chúng ta vẫn có thể cải thiện điều này. Bài viết này sẽ hướng dẫn các bạn 1 số cách cải thiện tốc độ xử lý của PHP, cụ thể là PHP-fpm trên server Nginx.

    PHP-fpm là gì?

    Không phải tất cả Developer đều quan tâm tới tất cả các khía cạnh của DevOps, và trong số đó không phải ai cũng hiểu cách server xử lý trong 1 thời gian ngắn. Một điều thú vị là khi có 1 request tới server PHP thì không phải PHP xử lý nó trực tiếp mà là các máy chủ (Nginx / Apache), sau đó các máy chủ này mới quyết định truyền dữ liệu, type, header tới PHP.

    Trong các ứng dụng sử dụng PHP hiện tại, thì phần lớn file index được cấu hình là index.php, file sẽ nhận mọi request từ server tới. Bây giờ thì chính xác server đã gọi tới các file php như thế nào? Nếu tìm hiểu vấn đề này sâu xa thì tất mất thời gian, do đó ở bài này chúng ta chỉ tìm hiểu 1 cách sơ lược thôi. Đại khái trong giai đoạn mà web server Apache thống trị thì PHP là 1 module trong đó. Khi mà mỗi request được gửi tới server, server sẽ tiến hành xử lý 1 tiến trình (process), process này sẽ bao gồm xử lý php. Phương thức này sẽ gọi mod_php trong Apache, như vậy php là 1 module. Cách tiếp cận này có các hạn chế nhất định, điều mà Nginx đã giải quyết với php-fpm.

    Đối với php-fpm thì trách nhiệm quản lý cũng như các quy trình xử lý đều nằm trong chương trình PHP trong server. Nói 1 cách khác là web server (cụ thể là Nginx) sẽ ko quan tâm file PHP ở đâu, nó được load như thế nào nếu như biết cách gửi và nhận data từ nó. Nếu như bạn muốn, bạn có thể coi PHP trong trường hợp này như là 1 server khác và nó sẽ quản lý các tiến trình php trong các request được gửi tới.

    Nếu như bạn đã setup server Nginx, bạn sẽ thấy các cấu hình như sau:

    location ~ \.php$ {

    try_files $uri =404;

    fastcgi_split_path_info ^(.+\.php)(/.+)$;

    fastcgi_pass unix:/run/php/php7.2-fpm.sock;

    fastcgi_index index.php;

    include fastcgi_params;       

    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

    }

    Chú ý dòng fastcgi_pass unix:/run/php/php7.2-fpm.sock; Cấu hình này chỉ ra cho Nginx sẽ kết nối tới tiến trình PHP thông qua socket có tên là php7.2-fpm.sock . Do đó tất cả các request Nginx gửi data tới file này và nhận output sau đó trả về cho browser.

    Tóm lại điều chúng ta cần nắm được ở đây là

    • PHP không trực tiếp nhận các request từ trình duyệt, các web server (Nginx) sẽ chặn chúng
    • Các web server biết cách kết nối tới các tiến trình PHP và gửi các dữ liệu tới chúng.
    • Sau khi các tiến trình PHP xử lý xong chúng sẽ trả output về các web server, web server sẽ trả lại các client

    Vậy cuối cùng PHP-FPM là cái gì?

    FPM là viết tắt của “Fast Process Manager” điều này có nghĩa là PHP chạy trên server không phải là một tiến trình đơn lẻ, mà nó bao gồm nhiều tiến trình được sinh ra, điều khiển, tắt bới trình quản lý fpm. Nó chính là trình quản lý mà web server sẽ gửi các request tới.

    Tại sao phải tối ưu php-fpm?

    Nếu server của bạn vẫn đang đáp ứng tốt nhu cầu sử dụng, cũng như đang ổn định thì tất nhiên không việc gì phải tối ưu nó cả. Tuy nhiên trong trường hợp server của bạn đang không đáp ứng đủ nhu cầu, cũng như lượng server của bạn bị hạn chế thì việc tối ưu từng server lại là điều cần thiết.

    Một khía cạnh khác là Nginx được xây dựng để xử lý 1 số lượng công việc khổng lồ, nó có thể đáp ứng hàng nghìn kết nối, và thật lãng phí nếu như bạn không sử dụng hết sức mạnh của nó để tối ưu tài nguyên vì Nginx sẽ phải chờ tiến trình PHP hiện tại xử lý xong mới xử lý tới request tiếp theo, điều này không đúng với những ưu điểm mà Nginx được tạo ra.

    Vậy tối ưu php-fpm như thế nào?

    File cấu hình của php-fpm ở các server có thể sẽ khác nhau, với ubuntu thì nó được để tại /etc/php/7.2/fpm/php-fpm.conf (Đây là đường dẫn của php version 7.2)

    Một vài config ban đầu bạn có thể thấy

     ;;;;;;;;;;;;;;;;;;;;;
    ; FPM Configuration ;
    ;;;;;;;;;;;;;;;;;;;;;
    
    ; All relative paths in this configuration file are relative to PHP's install
    ; prefix (/usr). This prefix can be dynamically changed by using the
    ; '-p' argument from the command line.
    
    ;;;;;;;;;;;;;;;;;;
    ; Global Options ;
    ;;;;;;;;;;;;;;;;;;
    
     [global] 
    ; Pid file 
    ; Note: the default prefix is /var 
    ; Default Value: none 
    pid = /run/php/php7.2-fpm.pid 
    ; Error log file 
    ; If it's set to "syslog", log is sent to syslogd instead of being written 
    ; into a local file. 
    ; Note: the default prefix is /var 
    ; Default Value: log/php-fpm.log 
    error_log = /var/log/php7.2-fpm.log 

    Một vài điểm cần chú ý trong cấu hình trên:

    pid = /run/php/php7.2-fpm.pid 

    Cấu hình này chỉ ra file chứa process id của tiến trình php-fpm

    error_log = /var/log/php7.2-fpm.log

    Còn đây là cấu hình file mà php sẽ ghi log.

    Bên cạnh đó còn 3 cấu hình

    emergency_restart_threshold 10
    emergency_restart_interval 1m
    process_control_timeout 10s

    Hai dòng đầu chỉ ra rằng nếu 10 quy trình con không thành công trong vòng 1 phút thì php-fpm sẽ tự động khởi động lại. Điều này nghe có vẻ “yếu” nhưng thực ra PHP là một tiến trình ngắn, nó làm tốn dữ liệu vì vậy việc khởi động lại trong trường hợp lỗi sẽ giải quyết được nhiều vấn đề. Cấu hình thứ 3 là thời gian các tiến trình con chờ đợi tín hiệu từ tiến trình cha .

    Thực ra bên trên vẫn chưa phải là cấu hình chính của php-fpm. Bởi vì để phục vụ các request từ server, php-fpm tạo ra một pool mới để quản lý các tiến trình, và nó sẽ có các cấu hình khác nhau. Ví dụ 1 pool có tên là www. File config là: /etc/php/7.2/fpm/pool.d/www.conf

    ; Start a new pool named 'www'. 
    ; the variable $pool can be used in any directive and will be replaced by the 
    ; pool name ('www' here) 
    [www] 
    ; Per pool prefix 
    ; It only applies on the following directives: 
    ; - 'access.log' 
    ; - 'slowlog' 
    ; - 'listen' (unixsocket) 
    ; - 'chroot' 
    ; - 'chdir' 
    ; - 'php_values' 
    ; - 'php_admin_values' 
    ; When not set, the global prefix (or /usr) applies instead. 
    ; Note: This directive can also be relative to the global prefix. 
    ; Default Value: none 
    ;prefix = /path/to/pools/$pool 
    ; Unix user/group of processes 
    ; Note: The user is mandatory. If the group is not set, the default user's group 
    ;       will be used. 
    user = www-data 
    group = www-data  

    Cấu hình mặc định thường như sau:

    pm = dynamic
    pm.max_children = 5
    pm.start_servers = 3
    pm.min_spare_servers = 2
    pm.max_spare_servers = 4
    pm.max_requests = 200

    Chú ý “dynamic” ở đây có ý nghĩa như thế nào. Xem các option có thể setting:

    ; Choose how the process manager will control the number of child processes.
    ; Possible Values:
    ;   static  - a fixed number (pm.max_children) of child processes;
    ;   dynamic - the number of child processes are set dynamically based on the
    ;             following directives. With this process management, there will be
    ;             always at least 1 children.
    ;             pm.max_children      - the maximum number of children that can
    ;                                    be alive at the same time.
    ;             pm.start_servers     - the number of children created on startup.
    ;             pm.min_spare_servers - the minimum number of children in 'idle'
    ;                                    state (waiting to process). If the number
    ;                                    of 'idle' processes is less than this
    ;                                    number then some children will be created.
    ;             pm.max_spare_servers - the maximum number of children in 'idle'
    ;                                    state (waiting to process). If the number
    ;                                    of 'idle' processes is greater than this
    ;                                    number then some children will be killed.
    ;  ondemand - no children are created at startup. Children will be forked when
    ;             new requests will connect. The following parameter are used:
    ;             pm.max_children           - the maximum number of children that
    ;                                         can be alive at the same time.
    ;             pm.process_idle_timeout   - The number of seconds after which
    ;                                         an idle process will be killed.
    ; Note: This value is mandatory.

    Giải thích sơ lược thì như sau

    pm.max_children = Số process con (child processes) tối đa được tạo (tương đương tổng số request có thể phục vụ)
    pm.start_servers = Tổng số child processes được tạo khi khởi động php-fpm (được tính bằng công thức `min_spare_servers + (max_spare_servers – min_spare_servers) / 2` )
    pm.min_spare_servers = Tổng số child process nhàn rỗi tối thiểu được duy trì.
    pm.max_spare_servers = Tổng số child process nhàn rỗi tối đa được duy trì.

    Chúng ta có các option sau:

    • Static: fix cứng 1 số lượng process được duy trì
    • Dynamix: set số lượng min và max các process có thể được duy trì ở bất cứ thời điểm nào
    • ondemand: Các process sẽ được tạo ra và tắt đi theo yêu cầu

    Vậy các con số này có ý nghĩa như thế nào? Nếu như web server của bạn có lượng truy cập rất ít thì việc chọn cấu hình là dynamic sẽ rất phí tài nguyên, trong trường hợp này bạn có thể set pm.min_spare_servers = 3 và chọn option “ondemand” để server quyết định số lượng process.

    Trong trường hợp ngược lại với 1 web site có số lượng truy cập lớn, thì nên setting về static, và setting với số lượng tối đa mà server có thể sử dụng.

    Cách tính pm.max_children

    B1. Xác định số lượng bộ nhớ cần thiết trung bình cho 1 process php-fpm

    ps -ylC php-fpm --sort:rss

    Ouput sẽ tương tự như sau, column RSS sẽ chứa giá trị mà chúng ta cần xác định

    S UID PID PPID C PRI NI RSS SZ WCHAN TTY TIME CMD
    S 0 24439 1 0 80 0 6364 57236 - ? 00:00:00 php-fpm
    S 33 24701 24439 2 80 0 61588 63335 - ? 00:04:07 php-fpm
    S 33 25319 24439 2 80 0 61620 63314 - ? 00:02:35 php-fpm

    Như kết quả ở trên là khoảng 61620KB, tương đương với ~60MB/process
    B2: Tính toán ra pm.max_children

    Ví dụ server hiện tại có khoảng 4GB RAM, đang chạy cả web và DB, chúng ta sẽ tính con số ước lượng là DB hoạt động khoảng 1GB và 0.5G dành cho buffer. Với các con số như vậy thì dung lượng RAM còn lại cho hoạt động của php-fpm tương đương với: 4 – 1 – 0,5 = 2,5 GB RAM hoặc 2560 Mb.

    pm.max_children = 2560 Mb / 60 Mb = 42

    Làm tròn con số xuống (để đảm bảo server hoạt động không bị quá tải), thì pm.max_children = 40
    Cách tính pm.min_spare_servers

    pm.min_spare_servers có giá trị tương đương với 20% của pm.max_children.
    Nếu như với gía trị ở trên thì pm.max_spare_servers = 60% * 40 = 24
    Cũng có hướng dẫn ghi là pm.max_spare_servers = (cpu cores) * 4
    Cách tính pm.max_requests

    Tham số này chính là số lượng request xử lý đồng thời mà server có thể chịu tải được, giá trị phụ thuộc vào pm.max_children và số lượng request trên 1s vào server. Con số này tính toán cũng khá hên xui, nhưng có thể có 1 phương pháp là sử dụng tool ab của apache sau đó giảm giá trị dần dần sao cho phù hợp.

    ab -n 5000 -c 100 http://domain.com/

    Khi chạy command trên thì có nghĩa là tạo ra 5000 request với 100 session hoạt động cùng lúc truy cập vào url http://domain.com. Giá trị pm.max_requests có thể set là 1000 sau đó tăng/giảm dần đến mức phù hợp (Phù hợp là khi server vẫn còn chịu được tải).

    Cấu hình Nginx để tăng performance

    Mở file /etc/nginx/nginx.conf và điều chỉnh theo các hướng dẫn sau.
    Trước hết bạn cần nắm công thức:

    max_clients = worker_processes * worker_connections
    số lượng người truy cập tối đa Nginx có thể phục vụ bằng thông số worker_processes nhân với worker_connections. Mặc định sau khi cài đặt Nginx thì

    worker_processes = 1

    worker_connections = 1024.

    Các bạn cần chỉnh lại worker_processes bằng với số lượng CPU core trong server bạn cấu hình. Có thể xem số CPU Core thông qua lệnh sau:

    cat /proc/cpuinfo |grep processor

    Với số lượng CPU bằng 4 bạn có thể setting worker_processes  = 4, như vậy lượng truy cập tối đa sẽ là 4 * 1024

    Để tăng thêm số lượng connection bạn cũng có thể thay đổi thêm

    worker_rlimit_nofile 2048;

    Cấu hình này giúp bạn có thể setting worker_connections  lên tới 2048

    Ngoài ra các bạn cũng cần thiết giới hạn kích thước body của các http request và buffer dùng xử lý http request thông qua việc thêm hai thông số sau đây vào file cấu hình

    client_max_body_size 20m;

    client_body_buffer_size 128k;

    Tăng tốc bằng cache file. Với các file tĩnh trên server thì chúng ta hoàn toàn có thể cache lại bằng config

    location ~* .(jpg|jpeg|gif|png|css|js|ico|xml)$ {
    access_log off;
    log_not_found off;
    expires 360d;
    }

    Anh em đọc tham khảo. Bài cóp nhặt từ nhiều nguồn, khá hữu ích cho các anh em PHP.

  • Nguyên nhân và giải pháp để tối ưu và tăng tốc độ tải trang web

    • Tại sao tốc độ website lại chậm ?
    • Làm sau để khắc phục website quá chậm như vậy ?
    • Tăng tốc website bằng cách nào ?
    • Tốc độ website làm ảnh hướng đến việc SEO của tôi giải quyết thế nào ?

    Đối với những website cao cấp tốc độ tải trang rất quan trọng. Người dùng chỉ hứng thú với những website load nhanh, còn khi một trang web đáp ứng chậm, khách sẽ mất kiên nhẫn và khả năng họ quay lại sẽ là rất thấp. Như vậy, những người tìm kiếm thông tin thường rất sốt ruột khi phải đợi những trang web được tải xuống. Nếu những trang Web của bạn không đủ nhanh, nhiều người tìm kiếm thông tin sẽ ra đi mà không thèm xem trong website có thứ gì.

    Cải thiện tốc độ tải trang không chỉ quan trọng đối với người dùng mà còn quan trọng với công cụ tìm kiếm. Tháng 4 năm ngoái Google đã công bố tốc độ tải trang là một trong những yếu tố xếp hạng trong thuật toán của họ.

    Có vài điều giúp bạn có thể làm tăng tốc độ web site của bạn. Tất nhiên, bạn cần phải chắc chắn rằng web của bạn được lưu giữ bởi những máy chủ đáng tin cậy và nhanh. Ngoài việc lưu giữ website của bạn trên một máy chủ nhanh, bạn có thể làm những việc sau đây để cải thiện thời gian tải của những trang Web của bạn.

    Nguyên nhân phổ biến khiến tốc độ tải trang chậm

    Nguyên nhân phổ biến khiến tốc độ tải trang chậm

    – Cái đặt Plugin, Script,… từ bên thứ 3: Có rất nhiều Plugin cả miễn phí, cả trả phí rất hấp dẫn với bạn. Bạn cài đặt chúng vào và không biết chúng ảnh hưởng như thế nào đến tốc độ tải trang? Cài đặt quá nhiều ứng dụng bên thứ 3 thiếu kiểm soát chính là một trong những nguyên nhân hàng đầu tăng gánh nặng cho Website bạn.

    – Chưa tối ưu HTML, CSS, js..: Dư thừa mã css và js, viết mã tạo nhiều file css và js. Css dùng nhiều hình ảnh làm hình nền. Mã nguồn cồng kềnh, bừa bộn, là một nguyên nhân không nhỏ tăng dung lượng Website của bạn lên và từ đó sẽ khiến thời gian tải về tăng lên đáng kể.

    – Không gzip source code trong khi truyền tải dữ liệu đến người xem qua đường truyền internet.

    – Người coder không xóa các ghi chú trong quá trình phát triển website.

    – Hình ảnh chất lượng cao và nặng: Do kích thước hình ảnh quá lớn so với kích thước người dùng xem. Làm tăng thời gian tải trang web. Chúng tôi biết là trông chúng sẽ rất đẹp, hình ảnh sắc nét, nhưng nếu bạn cứ Update thẳng những tấm hình 4, 5MB hoặc hơn lên Web, bao giờ người dùng mới tải xong chúng đây?.

    – Dịch vụ hosting kém chất lượng: Khách hàng lớn nhưng cấu hình server thấp, bảo mật kém, khoản cách địa lý…

    – Người quản trị copy từ các nguồn như: tin tức báo trí, các diễn đàn… không xử lý lại thông tin làm tạo các mã mà hệ thống không hỗ trợ.

    – Lượng khác hàng truy cấp website lớn nhưng dịch vụ hosting chưa nâng cấp xứng tầm.

    – Sử dụng dịch vụ web (webservice) từ nhà cung cấp thứ ba hay bạn đặt quá nhiều quảng cáo.

    – Hacker add các đoạn mã ăn cấp thông tin người dùng hay thực hiện các lệnh nhằm phá hỏng hệ thống.

    – Sử dụng nhiều file flash ảnh hưởng đến quá trình xử lý của trình duyệt web.

    Và theo thống kê sơ bộ của ADC việc ảnh hưởng đến tốc độ website thì với hơn 50% là xuất phát từ công ty thiết kế web vì họ không tối ưu website trước khi bàn giao. Trong đó 20% từ nhà cung cấp hosting, không tối ưu hóa và chất lượng dịch vụ hosting không đảm bảo. Còn lại 30% chính từ người quản trị website không am hiểu hệ thống.

    Những giải pháp phổ biến để tối ưu và tăng tốc độ tải trang web

    Những giải pháp phổ biến để tối ưu và tăng tốc độ tải trang web

    Chứa hình ảnh của website ở các domain khác nhau. Các dịch vụ như Amazon S3 làm chuyện này rất dễ dàng. Tạo 1 tài khoảng S3. Trỏ subdomain như “abc.yoursite.com” về S3 lưu trữ. Đặt các hình ảnh website của bạn ở đây. Các trình duyệt web có thể load từ nhiều domain cùng một lúc, tạo cảm giác rằng website của bạn load nhanh hơn. Hơn nữa, bạn sẽ sử dụng ít CPU và bandwidth của server chính hơn.

    Sử dụng Flickr để chứa hình ảnh website của bạn và dùng như một domain riêng.

    Nén các file hình ảnh theo đúng loại file nén. Sử dụng loại nén “lossy” – JPEG cho các hình ảnh nhiều màu sắc. Sử dụng loại nén “lossless – PNG và GIF – cho các hình ảnh ít màu sắc.

    Resize hình ảnh trước khi bạn upload chúng. Đừng resize hình ảnh theo chiều rộng và cao. Resize chúng bằng Photoshop, Fireworks hoặc các chương trình xử lí ảnh chuyên nghiệp.

    Học cách viết code thật rõ ràng, súc tích. Các hệ quản trị nội dung (CMS) hoặc các shopping cart thường phát sinh rất nhiều code HTML dư thừa. Xóa bỏ bớt hoặc làm gọn nó khi cần thiết.

    Đưa các cấu hình CSS vào các file .css riêng biệt, không nên nhúng thẳng vào mỗi trang.

    Chia rõ các cấu hình CSS ra. Tạo 1 stylesheet chứa duy nhất cấu hình sử dụng chung cho tất cả các trang. Sau đó, tạo các stylesheet riêng biệt cho mỗi layout của từng trang như: trang chủ, trang sản phẩm, trang tin tức,…Chỉ load những gì cần thiết trên mỗi trang.

    Học cách sử dụng CSS. Nếu bạn có thể sử dụng thẻ <p> thay vì sử dụng &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color=”blue” style=”font-size:10pt;font-weight:bold;”>, bạn sẽ tiết kiệm được rất nhiều không gian.

    Đưa các đoạn mã javascript vào các file .js. Không nên nhúng thẳng vào mỗi trang. Nếu bạn nhúng javascript vào thì cứ mỗi lượt viếng thăm trang web, kể cả Googlebot, đều phải download code đó mỗi lần tại mỗi trang. Nếu bạn tách riêng ra một file .js thì Googlebot sẽ bỏ qua nó và các browser sẽ cache nó lại được.

    Tách riêng các file javascript ra, giống như bạn tách riêng các file CSS vậy.

    Hoãn lại việc load các javascript khi có thể. Bạn có thể search Google với từ khóa “deferred javascript” để biết thêm chi tiết. Về cơ bản, kỹ thuật này sẽ cho các web browser biết nó sẽ load các javascript có thuộc tính “defer” cuối cùng, sau khi đã load hết các thành phần các của trang web. Điều này sẽ làm giảm nguy cơ bị chậm, bị lỗi hoặc bị đứng đang web khi các file javascript bị lỗi.

    Mã: http://common.js

    Bỏ các file Flash. Có rất nhiều cách để hiển thị các thành phần động trên một trang. Nếu bắt buộc sử dụng Flash, bạn nên sử chỉ sử dụng ở 1 phần nhỏ trên trang web.

    Sử dụng chuẩn nén GZIP trên web server của bạn.

    Giảm thiểu mọi thứ từ HTML, javascript cho đến CSS. Lưu lại một bản chưa được tối ưu của tất cả mọi thứ để chỉnh sửa lại sau này.

    Tối thiểu hóa việc redirect. Không sử dụng 301 redirect trừ khi bạn bắt buộc phải dùng.

    Sửa lại các vấn đề phù hợp với tiêu chuẩn chung. Sửa lại không có nghĩa là sử dụng “rel=canonica”, mà nó có nghĩa là phải đảm bảo rằng trên mỗi trang website của bạn phải có một địa chỉ đơn. Điều này sẽ làm tăng caching performance, giảm memory usage và tăng tốc mọi thứ lên.

    Đầu tư vào hosting có chất lượng tốt, uy tín. Nếu quy mô website lớn, lượng truy cập nhiều thì nên cân nhắc đầu tư một dedicated server để có thể tối đa được tốc độ website.

    Thiết lập caching trên server. Nếu bạn sử dụng WordPress, sử dụng plugin như W3 Total Cache.

    Go static. Nếu bạn đang xây dựng trang web với ngôn ngữ PHP, ASP hoặc ngôn ngữ nào khác thì các sự thay đổi thường xảy tra trên tất cả các trang đó. Một vài trang như “Giới thiệu”, “Liên hệ” việc thay đổi ít xảy ra nên bạn có thể để những trang đó là static (.html hoặc .htm). Làm như vậy sẽ giảm thiểu được một số lượng call tới CPU server, tăng performance.

    Nếu bạn đang làm việc với ngôn ngữ .NET, nghiên cứu để nén biến VIEWSTATE.

    Cấu hình đúng phần quản lý bộ nhớ của server (server’s memory management). Bạn tìm hiểu chi tiết thêm phần này ở Google nhé.

    Đặt database ở một server khác. Nếu bạn có một website với nhiều traffic, lượng truy cập lớn, khi đó bạn nên để website ở một server riêng và database ở một server riêng khác. Các database transaction tiêu tốn rất nhiều hiệu năng server.

    Học cách sử dụng JOIN để viết các câu truy vấn SQL lấy dữ liệu ở nhiều bảng khác nhau. Sử dụng JOIN sẽ nhanh hơn nếu dùng đúng cách.

    Học cách sử dụng Stored Procedures. Stored Procedures được biên dịch bởi database server và chạy nhanh hơn rất nhiều so với các script SQL thuần.

    Không sử dụng SSL trừ khi bạn buộc phải dùng nó (cách này còn gây rất nhiều tranh cãi, nên tạm thời không bàn chi tiết ở đây)

    Nếu bạn sử dụng Apache Server, chỉ nên load những module cần thiết. Hầu hết người dùng đều để thiết lập mặc định, và như vậy sẽ bao gồm những module không cần thiết. Học cách sử dụng AllowOverride, khi bạn thực sự cần DNS lookup, và các tip khác như FastCGI.

    Nếu bạn sử dụng Information Server (IIS), học cách sử dụng performance logging. Bạn có thể bắt đầu với trang Technet (http://technet.microsoft.com/en-us/library/bb727100.aspx). Nhớ kiểm tra IIS version mà bạn đang sử dụng.

    Học cách sử dụng một server accelerator như Squid, hoặc sử dụng Apache hoặc nginx như là một caching proxy. Các caching proxy và accelerator được thiết kế để lưu giữ các trang web động và phân phối chúng ra public một cách nhanh hơn.

    Lưu ý: Tùy theo từng trường hợp mà sẽ đưa ra các giải pháp khác nhau. Đảm bảo tốc độ tài trang chậm nhất dưới 3s

    Ngoài ra còn có nhiều cách khách cho bạn tối ưu trang của mình, và một website không bao giờ là “đủ nhanh” cả (thường các chuyên gia SEO khuyên nên tối ưu load trang dưới 3 giây).

    Điều quan trọng là bạn phải liên tục cải tiến, làm cho tốc độ của nó càng ngày càng nhanh. Khi đó bạn sẽ thấy được kết quả tốt hơn như: khách viếng thăm nhiều hơn, traffic nhiều hơn, xếp hạng cao hơn,…

    ST

  • Không bỏ lỡ các mail quan trọng với mailbox đầy màu sắc!

    Hàng ngày các bạn phải làm việc với hàng ngàn e-mail từ hàng ngàn người khác nhau. Vậy làm thế nào để các bạn không bị bỏ qua các mail quan trọng. Hãy sử dụng [Conditional Formating]. Bên dưới tôi sẽ hướng dẫn các bạn thực hiện settings mail box màu sắc theo độ quan trọng của từng e-mail.

    Với Outlook 2019 và 2016:

    1. Vào View tab
    2. Chọn View Settings
    3. Chọn Conditional Formatting
    4. Click Add
    5. Đặt tên cho Rule của bạn
    6. Click vào Font để setting màu sắc font chữ
    7. Lựa chọn Color, Style, Size mà bạn muốn
    8. Click vào Condition button. 

    Bạn có thể lựa chọn nhiều cách để filter mail khác nhau. Tôi thì hay dùng Query builder vì nó có khả năng filter mạnh mẽ hơn. Làm thế nào để enable Query builder bạn có thể tham khảo link này:

    Sau các setting này là bạn đã có mailbox đầy màu sắc như bên dưới. Tôi thì thường để các mail quan trọng có màu đỏ & đậm các mail không quan trọng màu nhạt và thiên về màu xanh hơn.

    Nếu bạn muốn apply cho các folder mail khác các bạn có thể làm như bên dưới:

    1. Chọn View Tab
    2. Chọn Change Views
    3. Chọn Apply Current View to Other Mail Folders.
    4. Lựa chọn folder mà bạn muốn apply Rule. 
    Outlook 2019 apply view to other email folders
  • Command Tip, Tip and Tips

    Command Tip, Tip and Tips

    Bài này hỗ trợ anh em khá nhiều trong việc sử dụng Command Line trong công việc, tuy nhiên mình sẽ giới hạn ở UNIX-like command thôi, dùng ở Linux, Mac, BSD ý.

    TIP 1: Search History Command

    Trong mấy năm thấy mọi người dùng nút up để mò lại những câu lệnh đã gõ. Ví dụ mình gõ lsof -i :22 và sau đó gõ 5 câu lệnh nữa, vậy là mình sẽ cần ấn nút up 5 lần. Nghe có vẻ mất thời gian và tay to và nhiều câu lệnh quá dài hay khó nhớ.

    Tình cơ thì Linux hay Mac đều lưu trữ lại câu lệnh mà mình đã gõ, có thể tìm thấy ở các file .history hay đơn giản là gõ history

    Mình thêm |tail để lấy ra các lệnh gần nhất thôi

    Vậy là chúng ta có thể history | grep {batkicaigi} để tìm kiếm

    Vậy vẫn hơi lâu, nếu ấn một nút để search thì sao, rất may cái nãy cũng được hỗ trợ luôn Ctrl + R và gõ thôi

    Vấn đề nữa xảy ra, quá ít kết quả được hiển thị, khá là khó chịu. Sau một hồi search thì phát hiện ra có nhiều thứ hỗ trợ mình trong đó có thằng này: peco, một tool filter được viết bằng Go Lang, chúng ta có thể truyền bất kì cái gì vào trong pipe của câu lệnh, từ history, ls, text file hoặc bất kì cái gì.

    Giờ hãy kết hợp history search (Ctrl + R) và peco.

    How to install

    $ brew install peco
    ...
    $ peco --version
    $ peco version v0.5.1
    

    À đấy là MAC còn cái khác thì chịu khó đọc cái này.

    Tiếp theo thì sửa cái .zshrc hoặc .bashrc, tùy xem bạn dùng cái gì, đơn giản là sửa binding key cho phím Ctrl + R thôi.

    # Peco history selection
    function peco-history-selection() {
      local tac
      if which tac > /dev/null; then
        tac="tac"
      else
        tac="tail -r"
      fi
      BUFFER=$(history -1000 | eval $tac | cut -c 8- | peco --query "$LBUFFER")
      CURSOR=$#BUFFER
    }
    zle -N peco-history-selection
    bindkey '^R' peco-history-selection
    

    và reload lại

    $ source .zshrc (or .bash_rc)
    

    Thành quả nè

    Còn mấy cái liên quan đến peco nữa nhưng để dịp sau vậy.

  • Webserver (Part 2)

    Webserver (Part 2)

    Trong Phanaf

    Trong phần trước, mình đã đề cập đến Host, WebServer. Vậy magz.techover.io hay google.com từ đâu mà có. Phần này sẽ tiếp tục với DNS.

    DNS

    Như phần trước, chúng ta có Host header, header này báo cho WebServer website mà client yêu cầu, vậy làm cách nào mà khi chúng ta điền google.com lên thanh URL và request đó đến đựoc WebServer?

    Đó chính là nhiệm vụ của DNS – Domain Name Service, đúng như cái tên nó là một service cung cấp tên miền (Domain Name). Khi chúng ta mua domain từ một nhà cung cấp (ví dụ như godaddy.com, hay namecheap.com), chúng ta thường thêm một số Domain Name Server vào domain đó. Nó sẽ kiểu như này:

    Domain name Server của một domain sử dụng AWS Route53

    Thực ra vụ này cũng không cần thiết lắm, vì nhiều nhà cung cấp cài đặt sẵn cho mọi người rồi, mọi người chỉ cần làm việc này khi chuyển việc quản lý domain cho service khác thôi (ví dụ khi mua bạn mua ở namecheap.com) và bạn chuyển qua cloudflare.com)), và chuyện này cũng phổ biến và thậm chí được khuyên dùng, lý do: security và high availability. Nhiều Name Server đã bị tấn công nhiều lần, khi đó, DNS sẽ không hoạt động và tất nhiên trang web của bạn cũng không thể truy cập bằng domain. Dùng nhiều DNS khác nhau cũng là một cách, vì bạn có thể setup nhiều ns record, một cách dễ hiểu là đừng bỏ trứng vào chung rổ và tất nhiên có nhiều bên cung cấp service này:

    • AWS Route 53
    • CloudFlare DNS
    • DynDNS
    • OpenDNS
    • EasyDNS
    • DNSMadeEasy

    Một khi Name Server của bạn được cài đặt, bạn có thể bắt đầu tạo DNS record ở trang web hay công cụ của nhà cung cấp Domain, đợi một vài phút là bạn có thể truy cập trang web của bạn từ trình duyệt.

  • Lan man về trình biên dịch (compiled) và trình thông dịch (interpreted)

    Chắc hẳn các bạn đã rất quen thuộc với 2 cụm từ “trình biên dịch” và “trình thông dịch”.
    Mình xin phép tổng hợp lại và cùng nhau tìm hiểu kỹ hơn một chút nhé.

    Theo SGK Tin học lớp 11:

    Có một vài thứ ta cần bàn đến ở đây.
    Trước hết hãy làm rõ “biên dịch” và “thông dịch”.

    • Biên dịch là chuyển các tài liệu từ ngôn ngữ này sang ngôn ngữ khác, đảm bảo độ chính xác.
    • Thông dịch là chuyển nhanh các thông điệp từ ngôn ngữ này sang ngôn ngữ khác, đảm bảo độ chính xác.
      Người ta đưa thêm một từ “trình” vào trước để ám chỉ rằng, nó là khái niệm dành cho máy để phân biệt với “biên dịch viên” và “thông dịch viên” mà chúng ta vẫn hay dùng cho con người.

    Hãy tưởng tượng xem, trình biên dịch và trình thông dịch làm gì với một đoạn mã lệnh nhé.
    a. Trình biên dịch: lần lượt thực hiện các bước sau:
    B1: Duyệt, kiểm tra, phát hiện lỗi, xác địch chương trình nguồn có dịch được không.
    B2: Dịch chương trình nguồn thành chương trình đích để máy hiểu và lưu trữ lại.
    b. Trình thông dịch: lần lượt thực hiện các bước sau
    B1: Kiểm tra tính đúng đắn của câu lệnh
    B2: Chuyển đổi câu lệnh nguồn thành câu lệnh tương ứng trong ngôn ngữ máy
    B3: Thực hiện các câu lệnh vừa chuyển đổi

    Chung lại, trình biên dịch sẽ chuyển đổi toàn bộ mã nguồn sang mã máy, rồi chứa kết quả vào ổ đĩa cứng để có thể thực thi ở lần chạy sau. Chương trình ngôn ngữ cấp cao được chuyển đổi gọi là chương trình mã nguồn (source program) và chương trình ngôn ngữ máy tạo ra gọi là chương trình đối tượng (object program) hoặc mã đối tượng (objectcode).
    Cách hoạt động của trình thông dịch khác so với trình biên dịch. Thay vì chuyển đổi toàn bộ mã nguồn sang chương trình đối tượng thì cứ khi nào chạy thì trình thông dịch hoạt động chuyển sang mã máy và đưa ra kết quả ngay. Công việc này sẽ diễn ra tương tự ở lần chạy tiếp theo. (theo http://kienthucweb.net/nao-la-trinh-bien-dich-va-thong-dich.html)
    Một vài ngôn ngữ thông dịch phổ biến: PHP, Javascript, Perl, …
    Một vài ngôn ngữ biên dịch phổ biến: C, C++, Java, …
    Vậy thực sự cái gì làm công việc dịch này?
    Cụ thể, trong C là GCC, còn trong PHP là Zen Engine VM.
    Và đây là những gì diễn ra khi chúng ta chạy một đoạn mã PHP, tham khảo bài viết dưới đây:
    https://techmaster.vn/posts/34207/php-chay-nhu-nao-tu-source-code-den-render

    Có 2 thứ ta cần cùng nhau làm rõ hơn đó là, cái đích cuối cùng của cả 2 đều phải tạo ra một thứ ngôn ngữ mà máy phải hiểu và có thể chạy.
    Vậy có 2 vấn đề:

    1. Máy ở đây hiểu là gì?
    2. Thứ ngôn ngữ như thế nào thì máy hiểu?

    Vấn đề thứ nhất, máy chính là CPU (Central Processing Unit), nó chính là bộ xử lý trung tâm, là các mạch điện tử thực hiện các câu lệnh của chương trình bằng cách thực hiện các phép tính số học, logic, so sánh, các hoạt động nhập/xuất dữ liệu (I/O) cơ bản do mã lệnh chỉ ra. (tham khảo: https://vi.wikipedia.org/wiki/CPU)
    Vấn đề thứ 2, ngôn ngữ máy là ngôn ngữ nhị phân (biểu diễn dưới dạng các chuỗi bit 0, 1).

    Lại có câu hỏi khác được nêu ra, tại sao CPU hiểu được các bit 0, 1?
    OK, câu trả lời là: CPU hiểu được vì các bit 0 và 1 biểu diễn cho tín hiệu điện, 1 tương ứng với “bật”, 0 tương ứng với “tắt”.
    Mã máy chạy trong CPU là dãy các tín hiệu xung điện (0 và 1) mà trình biên dịch hoặc trình thông dịch đã tạo ra.

    Một CPU có tầm vài triệu con transistor (hoặc nhiều hơn), hầu hết vai trò của chúng là các cổng logic, làm nhiệm vụ đóng hoặc mở tùy vào tín hiệu xung điện (là 0 hoặc 1).

    Phù, lằng nhằng phết nhỉ. Đến đây mình xin phép dừng lại, vì có quá nhiều thứ phải đọc, phải tìm hiểu. Nhưng ít nhất mình cũng hình dung ra được cái cách mà máy tính nó làm việc khi ta chạy một đoạn mã lệnh.

  • Webservers

    Webservers

    Về cơ bản bài viết này đưa cho các bạn khái niệm rất cơ bản về WebServer, các bạn web developer có thể rất cần Đầu tiên, mình nghĩ chúng ta nên đề cập đến HTTP, làm thế nào để match incoming HTTP request với website, sau đó là 2 Web Server rất phổ biến: Apache và Nginx, cuối cùng sẽ đề cập đến 1 ngôn ngữ cụ thể và cách kết nối với web server ở đây là PHP với PHP-FPM.

    HTTP, Web Server và Web Sites

    Mọi người có lẽ đều nghĩ rằng một WebServer chỉ có thể xử lý phục vụ một trang web, nhưng thực sự là ngược lại. Trong Apache thì dùng khái niệm VirtualHost, còn Nginx sử dụng bằng cách định nghĩa Server trong Nginx Configuration hay còn gọi là Virtual Servers.

    Nếu một WebServer đang xử lý nhiều trang web, làm thế nào để máy chủ định tuyến đến đúng trang web mà người dùng muốn truy cập?

    Chúng ta quay lại với HTTP – HyperText Transfer Protocol, là một trong năm giao thức chuẩn của mạng Internet, giao thức sử dụng để giao tiếp giữa WebServer và WebClient. Về cơ bản, WebServers sẽ đọc Host header của các Web HTTP request, nếu không tồn tại Host header hoặc không phù hợp, WebServer sẽ chuyển yêu cầu đến một trang web mặc định.

    Chúng ta có thể dùng curl để kiểm tra. Ví dụ mình sẽ kiểm tra magz.techover.io và Google.

    Chúng ta có thể thấy IP của WebServer là 104.28.19.140, chúng ta dùng curl để xem response khi gọi đến địa chỉ này.

    Chúng ta có thể thấy là magz.techover.io sử dụng Cloudflare để bảo vệ, và chúng ta bị chuyển đến trang mặc định 403 khi không có quyền truy cập.

    Còn với Google:

    Có thể thấy Google sử dụng GWS – Google Web Server. GWS thông báo cho Client rằng, Client cần phải truy cập đến http://www.google.com thông qua Location Header. Có 2 điều bạn thấy ở đây:

    • http://www.google.com mới là trang mặc định, thay vì http://google.com (cái này liên quan đến một khái niệm khác http://google.com được gọi là Naked Domain Name, sẽ có một bài viết liên quan đến vụ này sau).
    • GWS gửi một response chuyển hướng 301 đến http://www.google.com.

    Bây giờ nếu thêm Host header vào trang web thì sao:

    Kết quả không khả quan lắm, có vẻ như magz.techover.io và google.com vẫn không phải trang mặc định. Với trường hợp của magz.techover.io là do cloudflare chuyển hướng với non-SSL request sang SSL site.

    Đến đây một session mới được khởi tạo với Set-Cookie Header. Chúng ta có thể thử với một static site khác, site này không hề có Set-Cookie Header.

    Phần tiếp theo sẽ nói về việc cài đặt và cấu hình Nginx và Apache cho một hoặc nhiều Website.

  • Cách upload 1 App iOS lên Deploygate

    Cách upload 1 App iOS lên Deploygate

    Xin chào mọi người, hôm nay mình sẽ hướng dẫn các bạn cách upload 1 app lên Deploygate

    Thông thường việc cài đặt ứng dụng sẽ được thực hiện thông qua App Store, tuy nhiên sẽ có một số trường hợp sẽ ta không cần phải đưa app lên App Store mà thiết bị vẫn có thể cài đặt được. đa số sẽ thuộc vào một trong hai trường hợp sau :

    • Testing: Trước khi release app, ta cần test ứng dụng, vì vậy việc cung cấp bản build để tester có thể test trước khi release là một điều cần thiết
    • In-house Applications: Là những ứng dụng chỉ được sử dụng internal trong một công ty hay tổ chức nào đó ( đối với những ứng dụng In-house application, ta cần có tài khoản Apple Developer Enterprise Program)

    Những điều bắt buộc

    1. Valid Apple developer program account (not the Apple Developer Enterprise Program)
    2. Máy tính chạy Mac OS X
    3. Đã cài Xcode

    Tổng quát

    Bên dưới là danh sách các bước bắt buộc để submit 1 app

    1. Tạo 1 record của app trên iTunes Connect
    2. Cấu hình XCode project cho việc distribution
    3. Export ipa file from xcode
    4. Upload app lên deploygate

    1. Tạo 1 record của app trên iTunes Connect Bạn phải tạo 1 record của app trên iTunes Connect trước khi bạn upload app lên App Store. Nó sẽ chứa tất cả thông tin cần thiết để có thể quản lý để xử lý và hiển thị app trên App Store. Xem thông tin chi tiết tại đây

    2. Cấu hình XCode project cho việc distribution Bạn phải nhập các thông tin để chứng thực app: Identity, Team, Bundle ID, import provisioning file, set version number,… Tạo 1 provisiong profile Xem thông tin chi tiết tại đây

    3. Export ipa file from xcode

    – Achieve app: bước đầu tiên bạn tạo 1 bản lưu trữ của app để build và lưu trữ thông tin app.

    • Chọn scheme hiện tại của app: Ở mục Build only device -> Generic iOS Device
    • Sau đó, trên thanh status bar trên cùng, chọn Product -> Archive Rồi đợi Xcode nó archive app, khi xong thì vô Window -> Organizer để xem cái bản mình vừa mới archive được, bạn cũng có thể xem các bản archive trước đó

    – tiếp theo chúng ta export ra file ipa Xem thông tin chi tiết ở đây

    4. Upload app lên deploygate

    bước 1: đăng ký tài khoản deploygate link đăng ký ở đây

    bước 2: sau khi đăng ký xong ta chọn account -> Organizations -> Create

    • tiếp theo ta điền đầy đủ các thông tin ở trong hình -> Create -> Finish

    bước 3 : Sau khi ấn Finish thành công thì việc còn lại của chúng ta là upload file ipa mà chúng ta export từ xcode lên đây

    • chọn upload App -> tìm tới folder lưu file ipa -> open -> upload
    • việc tiếp theo là chờ đợi tới khi việc upload thành công -> sẽ hiển thị ra một màn hình như bên dưới, tới được bước này thì xin chúc mừng các bạn đã upload thành công app của mình lên deploygate rồi đấy ^^
    • muốn lấy link để tải app của mình cho mọi người, ta chọn vào Add a link for sharing -> hệ thống sẽ tự sinh ra cho mình một link để tải app 😀

    Chúc Các bạn thành công ^^