Friday, June 24, 2016

Tối ưu tốc độ Web thông qua cấu hình chế độ nén dữ liệu truyền qua giao thức HTTP

Hiện tại hầu hết các Web Server đều hỗ trợ chế độ nén dữ liệu trao đổi qua giao thức HTTP bằng cơ chế nén GZIP. Chế độ này là giải pháp hết sức đơn giản giúp tăng tốc độ trang web, tiết kiệm băng thông trao đổi qua đó giúp tăng trải nghiệm người dùng.

Bài viết này tôi dướng dẫn các bạn cấu hình để thực hiện việc này. Nội dung bài viết gồm:
1. Vì sao cơ chế nén dữ liệu giúp tăng tốc độ website?
2. Cấu hình trên các server Web
     2.1 Cấu hình trên server Tomcat
     2.2 Cấu hình trên server Apache
     2.3 Cấu hình trên server ISS
     2.4 Cấu hình trên các server khác
3. Kiểm tra trên ứng dụng Web
4. Xử lý trên ứng dụng Android
5. Xử lý trên ứng dụng iOS

1. Vì sao cơ chế nén dữ liệu giúp tăng tốc độ website?

Hầu hết các website lớn trên thế giới như Amazon, Google, Alibaba... hay của Việt Nam như đều cấu hình chế độ này:

Đây là cấu hình cơ bản khi triển khai các ứng dụng Web nhưng nhiều kỹ sư triển khai vẫn chưa để ý việc này.

Giờ chúng ta sẽ tìm hiểu kỹ hơn tại sao cơ chế này lại giúp tăng tốc độ của ứng dụng Web? Thực tế khi server chưa hỗ trợ nén, khi bạn thực gửi request, dữ liệu trả về ở dạng text thuần với kích thước rất lớn, sẽ mất nhiều thời gian trong việc truyền tải dữ liệu:
https://laptrinh365.blogspot.com - Tối ưu tốc độ web qua HTTP 
Trong khi đó nếu server cấu hình chế độ nén, kích thước Response trả về sẽ giảm khoảng 5 đến10 lần, do đó thời gian tải dữ liệu sẽ nhanh hơn:
 https://laptrinh365.blogspot.com - Tối ưu tốc độ web qua HTTP
=> Như vậy: Kích thước file nhỏ hơn <=> Tải dữ liệu nhanh hơn <=> Người dùng happy hơn.

2. Cấu hình trên các server Web

2.1 Cấu hình trên server Tomcat

Để cấu hình chế độ nén trên server Tomcat bạn thực hiện các bước như sau:
  • Bước 1: Trong thư mục của Tomcat bạn mở tệp conf/server.xml bằng trình soạn thảo văn bản bất kỳ.
  • Bước 2: Tìm đến thẻ Connector
    https://laptrinh365.blogspot.com - Tối ưu tốc độ web qua HTTP 
  • Bước 3: Trong thẻ Connector, bạn thêm các thuộc tính với các giá trị như bên dưới:
     compression="on"  
     compressionMinSize="2048"  
     noCompressionUserAgents="gozilla, traviata"  
     compressableMimeType="text/html,text/xml,text/css,text/plain,application/json, application/javascript,text/javascript,application/x-javascript"  
    
    Kết quả cấu hình như ảnh dưới:
    https://laptrinh365.blogspot.com - Tối ưu tốc độ web qua HTTP
  • Bước 4: Sau khi cấu hình xong, bạn restart lại server để kích hoạt cấu hình mới.

2.2 Cấu hình trên server Apache

Để cấu hình chế độ nén trên server Apache bạn thực hiện các bước như sau:
  • Bước 1: Vào thư mục triển khai ứng dụng Web của bạn trên server Apache, tìm và mở tệp .htaccess 
  • Bước 2: Thêm các dòng sau vào tệp .htaccess:
     # compress text, html, javascript, css, xml:  
     AddOutputFilterByType DEFLATE text/plain  
     AddOutputFilterByType DEFLATE text/html  
     AddOutputFilterByType DEFLATE text/xml  
     AddOutputFilterByType DEFLATE text/css  
     AddOutputFilterByType DEFLATE application/xml  
     AddOutputFilterByType DEFLATE application/xhtml+xml  
     AddOutputFilterByType DEFLATE application/rss+xml  
     AddOutputFilterByType DEFLATE application/javascript  
     AddOutputFilterByType DEFLATE application/x-javascript  
     # Or, compress certain file types by extension:  
     <files *.html>  
     SetOutputFilter DEFLATE  
     </files>  
    
  • Bước 3: Sau khi cấu hình xong, bạn restart lại server để kích hoạt cấu hình mới.

2.3 Cấu hình trên server ISS

Để cấu hình chế độ nén trên server IIS bạn có thể sử dụng một trong hai cách sau:
  • Cách 1: Sử dụng giao diện 
    • Bước 1: Mở trình quản lý “IIS Manager”, chuyển tới mức mà bạn muốn quản lý.
    • Bước 2: Trong “Features View” bạn kích vào “Compression”.
    • Bước 3: Trên trang “Compression”, chọn “Enable static content compression”.
    • Bước 4: Kích vào nút “Apply” trong khung “Actions”.
  • Cách 2: Sử dụng dòng lệnh
    Đánh lệnh sau trong cửa sổ dòng lệnh:
     appcmd set config /section:urlCompression /doStaticCompression:True  
    
(Ngoài chế độ “Static content compression”, ISS còn hỗ trợ chế độ “Dynamic content compression” nhưng khuyến cáo không nên sử dụng chế độ Dynamic vì chế độ này làm tăng tải của CPU). 

2.4 Cấu hình trên các server khác

Hầu hết các server đều hỗ trợ chế độ nén này, vì thế bạn có thể dễ dàng tìm được hướng dẫn bằng Google.

3. Kiểm tra trên ứng dụng Web

Với ứng dụng web, để hỗ trợ chế độ nén HTTP, bạn chỉ cần cấu hình trên server, còn trong ứng dụng bạn không phải làm gì. Để kiểm tra server đã bật chế độ nén này chưa bạn có thể sử dụng các cách sau:
  • Cách 1: Với site public, có thể nhập trực tiếp link site vào ô ” Web Page URL” trên trang ”Online gzip test”: 
  • Cách 2: Bật Firebug trên trình duyệt, sau đó kiểm tra Response Headers, nếu thấy có header Content-Encoding: ”gzip” thì server đã hỗ trợ chế độ nén.

4. Xử lý trên ứng dụng Android

Trên ứng dụng Android, khi xử lý lấy dữ liệu HTTP, bạn cần thêm header:
 Accept-Encoding="gzip,deflate"  

Và khi nhận Response về bạn phải kiểm tra header Content-Encoding, nếu có trường này trong header trả về thì phải xử lý thêm. Đoạn mã dưới là ví dụ trong đó phần chữ màu xanh là phần xử lý nén:

 public static String readDataFromServer(String url) {  
      StringBuilder builder = new StringBuilder();  
      HttpParams httpParameters = new BasicHttpParams();  
      HttpConnectionParams.setConnectionTimeout(httpParameters, 30000);  
      HttpConnectionParams.setSoTimeout(httpParameters, 30000);  
      HttpClient client = new DefaultHttpClient(httpParameters);  
      HttpGet httpGet = new HttpGet(url);  
      httpGet.setHeader("Referer", "http://" + AppInfo.getAppId());  
      httpGet.setHeader("Accept-Encoding", "gzip,deflate");  
      try {  
           HttpResponse response = client.execute(httpGet);  
           StatusLine statusLine = response.getStatusLine();  
           int statusCode = statusLine.getStatusCode();  
           if (statusCode == HttpStatus.SC_OK) {  
                // Kiem tra xem du lieu tra ve co duoc nen hay khong?  
                Header[] header = response.getHeaders("Content-Encoding");  
                boolean isCompressed = false;  
                if (header != null && header.length > 0) {  
                     for (int i = 0; i < header.length; i++) {  
                          if (header[i].getValue().indexOf("gzip") >= 0) {  
                               isCompressed = true;  
                               break;  
                          }  
                     }  
                }  
                HttpEntity entity = response.getEntity();  
                InputStream content = entity.getContent();  
                InputStreamReader in = null;  
                if (isCompressed) {  
                     // Giai nen du lieu truoc  
                     GZIPInputStream gzis = new GZIPInputStream(content);  
                     in = new InputStreamReader(gzis);  
                } else {  
                     // Du lieu khong duoc nen  
                     in = new InputStreamReader(content);  
                }  
                BufferedReader reader = new BufferedReader(in, 10*1024);  
                String line;  
                while ((line = reader.readLine()) != null) {  
                     builder.append(line);  
                }  
           } else {  
                // Có lỗi xảy ra  
           }  
      }  
      catch (ConnectTimeoutException e) {  
           // Timeout  
      }  
      catch (Exception e) {  
           // Có lỗi  
      }  
      return builder.toString();  
 }  

5. Xử lý trên ứng dụng iOS

Trên ứng dụng iOS, có lớp NSURLConnection có hỗ trợ chế độ nén này trong suốt, tức khi thêm header Accept-Encoding thì khi nhận được response về sẽ tự giải nén:
 [urlReq setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"]  

No comments:

Post a Comment