Gần đây có nghiên cứu lại mấy vấn đề của Lambda function và mày mò vào Node Summit, bài viết này thực ra trình bày lại topic này của Matt Lavin
Về cơ bản với Lambda, AWS đã làm gần hết mọi thứ về management, scale function, kết nối đến các service như DynamoDB, SQS,… Gần như chúng ta chỉ cần chú ý đến việc coding là chính. Tuy nhiên để mọi thứ tốt hơn cho người dùng thì cần giảm latency, response nhanh hơn và dễ debug hơn trong những trường hợp cần thiết và chính trong source code Lambda function tức là:
Cải tiện latency
Tìm ra bug performance
Debug.
Bài này sẽ nói về các cách optimze coding là chính, những phần khác thì hãy xem kỹ topic nhé.
Đầu tiên bao giờ cũng cần tìm hiểu xem Lambda hoạt động như nào nhưng trước tiên mình sẽ đưa một ví dụ điển hình về lambda function:
Khá là điển hình với việc: Khởi tạo SDK, handle request, query database và đưa ra kết quả, tất nhiên trước đó sẽ là download source code và khởi chạy lambda function. Và hãy ghép nó vào mô hình lifecycle của lambda function như ở bên dưới.
Như hình bên trên toàn bộ Lifecycle của AWS Lambda bao gồm Cold Start và Warm Start.
Warm start: bao gồm phần thời gian code chạy
Cold start: thời gian chuẩn bị.
Như vậy có thể thấy rằng phần warm start là phần coding đơn thuần và optimze như chúng ta optimze source code khi sử dụng các framework hay runtime khác. Mặt khác, mọi người thường nghĩ rằng Lambda Function sẽ thực hiện toàn bộ các bước trên mỗi lần execute nhưng không Lambda sẽ không khởi chạy lại Cold Start, miễn là bạn không update source code nhưng chỉ trong 15 phút thôi nhưng vậy là quá đủ. Reduce latency sẽ bắt đầu từ đây.
Như hình trên cứ sau một khoảng thời gian nhất định Lambda function lại thực hiện Cold Start, những chỗ thời gian execute cao bất thường ấy, nhìn chung hãy để function Lambda luôn sẵn sàng để execute.
Một cách chính thống hơn thì có thể tìm hiểu ở đây, AWS đề cập đến Lambda execution context (Môi trường để running Lambda code), context này sẽ bị đóng băng sau khi sử dụng xong function và được giã đông khi chạy lần tiếp và AWS cũng đề xuất một vài thủ thuật để optimize Lambda function:
Đầu tiên bắt đầu với handler method, Các object được khai báo bên ngoài handler vẫn được khởi tạo, cung cấp tối ưu hóa bổ sung khi handler được gọi lại. Ví dụ: nếu Lambda connect đến database (RDS, DynamoDB), thay vì kết nối đi kết nối lại, kết nối được tái sử dụng qua các lần invoke khác nhau trong một lambda instance. Một cách đơn giản có thể lazy load connection, như bây giờ AWS đã cải tiến SDK để dùng keep alive hoặc đơn giản là chuyễn những thứ nặng nề ra khỏi handler, cache lại AWS SDK Client
const AWS = require('aws-sdk')
// http or https
const https = require('https');
const agent = new https.Agent({
keepAlive: true
});
const dynamodb = new AWS.DynamoDB({
httpOptions: {
agent
}
});
fuction fuckingHeavyFunction() {
}
const outsideHeavyResult = fuckingHeavyFunction(); // run on every Lambda init instance.
exports.handler = async (event) => {
const heavyResult = fuckingHeavyFunction(); // run on every lambda request
return response;
};
Mỗi Lambda function có 512Mb lưu trữ ở /tmp, bạn có thể lưu trữ bất kỳ thứ gì. Vùng lưu trữ này sẽ được đóng băng cùng với Execution context, như vậy bạn có thể lưu trữ nhiều thứ ở trong này, ví dụ những tính toán, variable ít thay đổi có thể lưu trữ lại và dùng lại cho lần tiếp theo.
Nếu sử dụng background process trong Lambda function, hãy chắc chắn nó được hoàn toàn hoàn thành khi Lambda function kết thúc, vì có thể nó được sử dụng lại và tiếp tục chạy. Dẫn đến những bug không như ý.
Nhưng nói chung cũng không nên nghĩ rằng Lambda sẽ sử dụng lại các tài nguyên khi chạy lại Lambda function, hãy chuẩn bị lại các tài nguyên hoặc kiểm tra việc sử dụng cho chắc chắn.
Vào terminal đi đến folder chứa Makefile gõ: •“make” – để chạy makefile •“make clean” – để clean các file thư viện .a được generate ra sau khi đã chạy ”make” ( Hàm này để đỡ phải xoá file .a = tay thôi)
Chú ý đường dẫn vào library mỗi máy khác nhau, và cái số ”12.4” là hỗ trợ iOS version mới nhất của Xcode, • Ex : Xcode 10.3 có hỗ trợ iOS mới nhất là 12.4 • Sau khi chạy lệnh trên, sẽ generate ra file ApiDefinition.cs
Đến đây là chúng ta đã hoàn thành bước tạo library rồi đó. Tiếp theo là sử dụng nó trong project Xamarin nhé .
5. Add binding library to project Xamarin
1. Click chuột phải vào Solution -> Add -> Add new project
2. Chọn iOS -> Library -> Bindings Library.
3. Next.
4. Kéo file .a vào binding library project vừa tạo
5. Alert hiện lên, chọn “Copy the file in the directory” -> OK Copy content trong file ApiDefinition.cs tại step 4 vào file ApiDefinition.cs trong project Xamarin này.
6. Sau đó nhấn chọn build Library project.
6. Add binding library to project Xamarin
Click chuột phải vào “References”, chọn “Edit references”.
Tích chọn Library project..
OK
7. Call library API
Sau khi thực hiện các bước ở trên chúng ta có thể gọi chúng như với các lib của Xamarin rồi
Mọi người làm Laravel cũng khá nhiều nhưng đã bao giờ đi sâu về tìm hiểu Laravel Model chưa hay dùng như thế nào cho hiệu quả.
Laravel Model hay chính xác hơn Eloquent Model là một class ActiveRecord để chúng ta làm việc dễ dàng hơn với database, sau đây thì có vài cái hay ho về Laravel Model.
Tạo model
php artisan make:model Flight
Ở guide của Laravel thì sẽ hướng dẫn như trên, và class Flight sẽ được tạo ở namespace App hay app folder.
php artisan make:model Models/Flight
Một cách tương tự thì chúng ta hay dùng App\Models vậy sao không tạo class luôn trong đó?
Bây giờ is_publish field sẽ luôn được trả về boolean, ngay cả khi chúng ta lưu trữ là 0 hay 1 trong database. Ngoài boolean` ra thì có thể cast nhiều cái khác ngay cảdatevàdatetime“`.
Một lỗi khá phổ biến là lỗi format thời gian, chúng ta trả ra nhiều kiểu format khác nhau: dd-MM-YYYY, YYYY-MM-dd.
Như vậy chúng ta không cần format date ở đâu nữa, kể cả các template framework dùng với Laravel.
Visibility
Một số thuộc tính không nên được trả về JSON response client, ví dụ như password. Chúng ta có thể ẩn nó đi, hay exclude khỏi response của model, như kiểu một blacklist vậy dùng $hidden.
protected $hidden = [
'password'
];
Ngược lại thì chúng ta lại có whitelist – $visible:
Với Accessors thì mọi chuyện đơn giản hơn, cú pháp nhắn tin như này:
get[NameOfAttribute]Attribute
đây là ví dụ:
public function getFullNameAttribute() {
return "{$this->first_name} {$this->last_name}";
}
Xong rồi gọi như này:
$full_name = $user->full_name;
Mutators
Tương tự như Accessors, thì Mutators dùng cho việc update giá trị, cú pháp cũng tương tự như Accessors luôn:
public function setLastNameAttribute($value) {
$this->attributes['last_name'] = ucfirst($value);
}
thì ví dụ
$user->last_name = 'hoang';
$last_name = $user->last_name; //cái này sẽ trả ra Hoang
//vì ucfirst sẽ capitalized cái chữ cái đầu
Appending values
Mặc định, Accessors với cả relations thì sẽ không được thêm vào array hay JSON của Model, vậy nếu cần thì chúng ta dùng $appends ví dụ với cái getFullNameAttribute như trên:
$appends = [
'full_name'
];
Có cái này hơi ngu chút: $appends thì vẫn sử dụng snake case còn Accessors thì sử dụng camel case.
Vụ appending với cả relations thì mọi người tự tìm hiểu nhé.
Touches
Khi model có relations BelongsTo hoặc BelongsToMany với model khác, trong trường hợp này, một Comment thuộc về Blog, trong một số trường hợp, chúng ta cần update timestamp của Blog khi edit hoặc thêm mới Comment. $touches có thể làm điều này.
class Comment extends Model
{
protected $touches = ['blog'];
public function blog()
{
return $this->belongsTo(App\Blog::class);
}
}
Trên đây là mấy cái mình vừa tìm hiểu được :D, có điều vẫn còn nhiều cái nữa, mong sẽ được chia sẽ trong những phần sau.
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, user và user_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:
Ứ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.
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.
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.
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)
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 (JWE và JWS)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ờ : )
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:
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
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
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
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
– 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
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 <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.
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,…
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:
Vào View tab
Chọn View Settings
Chọn Conditional Formatting
Click Add
Đặt tên cho Rule của bạn
Click vào Font để setting màu sắc font chữ
Lựa chọn Color, Style, Size mà bạn muốn
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:
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.
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.