Dùng nhiều máy chủ cho Website của bạn

0
1556
(Last Updated On: Th9 17, 2018)

Xin chào các bạn, trong thời đại thông tin ngày nay với sự phát triển bùng nổ của công nghệ cũng như là dân số thế giới ngày càng tăng thì nhu cầu sử dụng dịch vụ cũng ngày càng tăng lên. Đó là đang nói chung còn nói riêng về anh em nhà web chúng ta cũng phải làm sao để phục vụ được nhiều khách hàng hơn, tốc độ tải trang nhanh hơn cũng như là dự phòng khi máy chủ bị sự cố khiến website không thể truy cập được. Một phần điều này gây nên khó chịu cho người dùng một phần bạn có thể mất đi những khách hàng nếu như bạn gây dựng một trang bán hàng online chẳng hạn. Chưa nói nếu nó ảnh hưởng đến công việc của khách hàng hay người dùng thì khả năng bạn sẽ mất họ bởi họ sẽ đi tìm một dịch vụ khác tốt hơn,…

Có nhiều cách để giúp website của bạn truy cập nhanh hơn, chịu tải tốt hơn (chịu được nhiều truy cập cùng lúc, hay truy vấn) hoặc là có khả năng dự phòng, giảm thiệt hại do DDOS (ở đây mình nói là giảm chứ không phải chống – thực sự thì việc tấn công DDOS chỉ có thể giảm thiểu chứ không ngăn chặn hoàn toàn được), chẳng hạn như:

  • Sử dụng CDN
  • Cache
  • Load Balancing (cân bằng tải).
  • Multi Webserver (sử dụng nhiều máy chủ)
  • Round robin DNS (cũng là một kỹ thuật cân bằng tải).

Vâng và mình vào thẳng vấn đề luôn, như tiêu đề bài viết mà mình đã đặt. Hôm nay mình xin hướng dẫn các bạn cách sử dụng nhiều máy chủ cho Website của các bạn. Cách thức hoạt động là như thế này:

Đây là sơ đồ thiết lập của trang VnGeek hiện tại.

Kỹ thuật Round Robin DNS giúp phân tán và cân bằng tải cho nhiều máy chủ khác nhau, DNS server mà bạn thiết lập sẽ trả về các Record với các IP khác nhau mà bạn đã thiết lập trước đó, giả sử mỗi IP ứng với mỗi máy chủ dịch vụ khác nhau (ở đây là webserver) thì DNS server sẽ đưa người dùng lần lượt đến các máy chủ đã được gán IP trước đó, xoay vòng và cân bằng, kiểu như chia việc cho từng người. Như ông cha ta từng có câu: “Một cây làm chẳng nên non, ba cây chụm lại lên hòn núi cao!” vậy.

Để thực hiện điều trên chúng ta cần thực hiện hai tiêu chí:

  1. Tập tin web trên các máy chủ là giống nhau, ví dụ như người dùng sau khi truy vấn được đưa đến máy chủ A, họ tải lên một tập tin đến máy chủ A, thì tập tin này cũng phải được sao chép ngay tức thời (hoặc trong thời gian nhanh nhất) đến máy chủ B thì một người nào đó truy cập được đưa đến máy chủ B thì nó cũng giống như là máy chủ A (hiểu nôm na là tập tin mặc dù được tải lên ở máy chủ A, nhưng người dùng cũng có thể truy cập đến tập tin đó bên máy chủ B một cách bình thường, nãy giờ chúng ta nói máy chủ A và B, nhưng người dùng họ chỉ biết là đang truy cập đến cái trang VnGeek duy nhất, bởi tên miền và website ứng với miền chỉ có một mà thôi.
  2. Đồng bộ Database:
    Sau tiêu chí 1, việc tiếp theo rất quan trọng đó là đồng bộ database (cơ sở dữ liệu) trên cả 2 server. Thay vì tập tin thì bây giờ là những bài viết. Việc đồng bộ database không giống như sao chép những tập tin. Mà nó cần được thiết lập giữa các node với nhau (các node cài đặt các hệ cơ sở dữ liệu chẳng hạn như MySQL, Oracle, PostgreSQL, SQL Server,…). Ở đây trang VnGeek của mình sử dụng MySQL – hệ quản trị được khuyến nghị sử dụng cho WordPress. Cho nên mình sẽ thiết lập trên MySQL.

Các việc còn lại thì sẽ đơn giản hơn sau khi các bạn hoàn thành 2 tiêu chí trên.

Bây giờ mình tiến hành đồng bộ cơ sở dữ liệu trước nhé các bạn.

Để thiết lập ban đầu đơn giản, với Server A đang hoạt động ổn định, các bạn hãy Clone nó sang Server B. Đối với các bạn sử dụng các dịch vụ Cloud VPS, việc tạo một bản Snapshot và Restore nó lên một VPS mới đó là điều vô cùng đơn giản và dễ dàng. Nếu các bạn không có dịch vụ Snapshot đi kèm, các bạn có thể tham khảo bài viết Sao lưu và khôi phục máy chủ Ubuntu toàn diện trước đó để backup server hiện tại của các bạn và Restore nó trên một máy chủ khác môt cách nhanh chóng.

Bước 1: Thiết lập MySQL trên server A:

Chắc chắn là hệ cơ sở dữ liệu MySQL của các bạn hoạt động ổn định, nếu chưa thì cài đặt lại một lần nữa bằng dòng lệnh:

apt-get install mysql-server mysql-client

Sau khi cài đặt lại MySQL các bạn thiết lập cho phép được truy cập đến cơ sở dữ liệu này từ xa qua tập tin /etc/mysql/my.cnf

Các bạn chú ý có hai dòng:

#server-id              = 1
#log_bin                = /var/log/mysql/mysql-bin.log

Các bạn bỏ hai dấu thăng “#” để gán ID cho server này là 1 và lưu lại file log sau này chúng ta có thể xem tiến trình của MySQL cũng như những lỗi có thể xảy ra.

Trông như thế này là ổn.

Các bạn tiếp tục tìm đến dòng:

bind-address            = 127.0.0.1

Và thêm một dấu “# trước bind-address = 127.0.0.1 thành như thế này:

#bind-address            = 127.0.0.1

Việc vừa rồi là bạn cho phép có thể truy cập được máy chủ MySQL này từ xa, bởi nếu theo thiết lập mặc định, MySQL chỉ cho phép quyền truy cập đến từ 127.0.0.1 tức là localhost. Chỉ cho phép truy cập từ chính nó.

Sau đó tìm dòng:

#binlog_do_db           = include_database_name

Sau đó sửa thành:

binlog_do_db           = database_name

Trong đó database_name sửa thành tên database của bạn, nếu chưa tạo cũng không sao vì bạn có thể tạo database sau.

Như trong trường hợp mình, mình đã có database web từ trước đó của WordPress.

Tiếp tục thêm 2 dòng này vào tập tin my.cnf:

auto-increment-increment = 2
auto-increment-offset = 1

Bước tiếp theo chúng ta sẽ tiến hành đăng nhập vào MySQL để thiết lập user để có thể tạo cơ sở dữ liệu và đồng bộ giữa 2 server:

mysql -u root -p

Trong đó “root” là tên đăng nhập, sau đó bạn điền mật khẩu của user root mà bạn đã tạo trước đó khi cài MySQL nhé.

Sau khi đăng nhập thành công vào MySQL dòng lệnh trở thành như thế này:

Tiếp theo chúng ta thêm một user với tên là replicator và user này sau này sẽ có quyền để sao chép dữ liệu giữa 2 server.

create user 'replicator'@'%' identified by 'password';

Bạn thay password thành mật khẩu bạn mong muốn nhé.

Tiếp tục trao quyền cho user replicator có quyền sao chép dữ liệu trong MySQL:

grant replication slave on *.* to 'replicator'@'%';

Tiếp tục flush privileges cho user:

flush privileges;

Tiếp theo chúng ta kiểm tra trạng thái MySQL của server A:

show master status;

Bạn sẽ cần lưu lại những thông tin có được:

mysql> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 |      107 | web          |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.01 sec)

mysql>

Thông tin trên rất quan trọng để chúng ta tiếp tục thiết lập trên server B.

Chúng ta tiến hành khóa database để không cho sự thay đổi nào

flush tables with read lock;

Bạn hãy Export database hiện tại để tạo bản sao lưu dự phòng.

Mở khóa lại database:

unlock tables;

Bước 2: Thiết lập MySQL trên server B:

Tương tự như server A, bạn cài đặt MySQL:

apt-get install mysql-server mysql-client

Tiếp tục chỉnh sửa file: /etc/mysql/my.cnf

Hai dòng dưới này

#server-id              = 1
#log_bin                = /var/log/mysql/mysql-bin.log

Sửa thành thế này:

server-id              = 2
log_bin                = /var/log/mysql/mysql-bin.log

Tiếp tục tìm dòng:

bind-address            = 127.0.0.1

Thêm dấu “#” vào đằng trước:

#bind-address            = 127.0.0.1

Lưu lại là xong!

Các bạn thêm 2 dòng sau vào tập tin my.cnf:

auto-increment-increment = 2
auto-increment-offset = 2

Tiếp tục các bạn chỉnh sửa dòng:

#binlog_do_db           = include_database_name

Thành dòng:

binlog_do_db           = database_name

Trong đó database_name là tên database bạn đã có hoặc tạo (trùng tên như trên server A). trong trường hợp mình là “web”.

Như vậy là tương đối cấu hình xong tập tin thiết lập cấu hình trên MySQL.

Tiếp tục đăng nhập vào MySQL:

mysql -u root -p

Tạo một user replicator như trên server A:

create user 'replicator'@'%' identified by 'password';

Chú ý sửa password thành mật khẩu bạn mong muốn (mật khẩu như trên server A).

Sau đó thêm quyền để có thể sao chép cơ sở dữ liệu:

grant replication slave on *.* to 'replicator'@'%';

Và flush privileges:

flush privileges;

Sau đó các bạn chạy lệnh sau để khởi động lại dịch vụ của MySQL trên cả hai server A và B:

service mysql restart

Bước quan trọng sau đây là để 2 máy chủ MySQL có thể đồng bộ cơ sở dữ liệu cho nhau (Vẫn thực hiện trên Server B):

slave stop;

Tiếp sau đó:

CHANGE MASTER TO MASTER_HOST = 'aaa.aaa.aaa.aaa', MASTER_USER = 'replicator', MASTER_PASSWORD = 'password', MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 107;
  • Trong đó: aaa.aaa.aaa.aaa là dải IP của máy chủ A
  • MASTER_LOG_FILE: Thông tin trong mục File lúc dùng câu lệnh SHOW MASTER STATUS; trên server A.
  • MASTER_LOG_POS: Thông số trong mục Position.

Tiếp tục:

slave start;
Như vậy là đã thiết lập xong trên server B.

Các bạn đừng quên chạy lệnh:

SHOW MASTER STATUS;

Chúng ta cũng cần thông số để quay lại thiết lập trên server A:

Thông tin dưới dạng chữ như sau:

mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000008 |      226 | web          |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

mysql>

Và chúng ta tiếp tục đến bước 3 nào.

Bước 3: Thiết lập trên server A một lần nữa:

slave stop;

Tiếp sau đó:

CHANGE MASTER TO MASTER_HOST = 'bbb.bbb.bbb.bbb', MASTER_USER = 'root', MASTER_PASSWORD = 'Lenovo@0', MASTER_LOG_FILE = 'mysql-bin.000008', MASTER_LOG_POS = 226;
  • Trong đó: bbb.bbb.bbb.bbb là dải IP của máy chủ B
  • MASTER_LOG_FILE: Thông tin trong mục File lúc dùng câu lệnh SHOW MASTER STATUS; trên server B.
  • MASTER_LOG_POS: Thông số trong mục Position.
slave start;

Như vậy thì database web trên cả 2 server A và B bây giờ đã đươc thiết lập xong để đồng bộ với nhau, bản chất của công việc thiết lập trên thật sự là sử dụng mô hình Master-Slave.

A là Master, B là Slave và lần lượt A lại là Slave và B là Master.

Như vậy mọi thay đổi cơ sở dữ liệu như ghi, xóa,… trên A hay B thì server còn lại cũng chịu ảnh hưởng tương tự.

Chúng ta thử kiểm tra xem đã được đồng bộ cơ sở dữ liệu chưa:

Bây giờ mình thử tạo một table với tên VnGeek trên server B thử xem bên A có đồng bộ hay không nhé:

Tiến hành đăng nhập vào MySQL trên server B:

mysql -u root -p

Chọn database web:

mysql> use web

Tạo một table mới mang tên VnGeek:

mysql> create table web.VnGeek (`id` varchar(10));

Tiếp tục xem đã tạo được table VnGeek trong database web chưa:

mysql> show tables in web;

Như vậy là có Table VnGeek rồi này:

mysql> show tables in web;
+----------------------------------+
| Tables_in_web                    |
+----------------------------------+
| VnGeek                           |
| wp_bp_activity                   |
| wp_bp_activity_meta              |
| wp_bp_notifications              |
| wp_bp_xprofile_data              |
| wp_bp_xprofile_fields            |
| wp_bp_xprofile_groups            |
| wp_bp_xprofile_meta              |
| wp_cntctfrm_field                |
| wp_commentmeta                   |
| wp_comments                      |
| wp_comments_fbseo                |
| wp_cptch_images                  |
| wp_cptch_packages                |
| wp_cptch_whitelist               |
| wp_dprv_licenses                 |
| wp_dprv_post_content_files       |
| wp_dprv_posts                    |
| wp_email                         |
| wp_gdsr2_log                     |
| wp_gdsr2_multi                   |
| wp_gdsr2_multi_meta              |
| wp_gdsr2_multi_values            |
| wp_gdsr2_ratings                 |
| wp_gdsr2_ratings_meta            |
| wp_links                         |
| wp_microblogposter_accounts      |
| wp_microblogposter_items_meta    |
| wp_microblogposter_logs          |
| wp_microblogposter_old_items     |
| wp_microblogposter_user_accounts |
| wp_nxs_log                       |
| wp_oauth_access_tokens           |
| wp_oauth_authorization_codes     |
| wp_oauth_clients                 |
| wp_oauth_jwt                     |
| wp_oauth_public_keys             |
| wp_oauth_refresh_tokens          |
| wp_oauth_scopes                  |
| wp_options                       |
| wp_popularpostsdata              |
| wp_popularpostsdatacache         |
| wp_postmeta                      |
| wp_posts                         |
| wp_pppm_filter                   |
| wp_pppm_html                     |
| wp_pppm_polls                    |
| wp_pppm_polls_items              |
| wp_pppm_polls_votes              |
| wp_pppm_protocol                 |
| wp_pppm_shortcut                 |
| wp_rating_scores                 |
| wp_ratings                       |
| wp_relevanssi                    |
| wp_relevanssi_log                |
| wp_relevanssi_stopwords          |
| wp_revslider_css                 |
| wp_revslider_layer_animations    |
| wp_revslider_navigations         |
| wp_revslider_settings            |
| wp_revslider_sliders             |
| wp_revslider_slides              |
| wp_revslider_static_slides       |
| wp_signups                       |
| wp_smush_dir_images              |
| wp_ssubscribe_app                |
| wp_subscribers                   |
| wp_subscribers_log               |
| wp_supsystic_tbl_columns         |
| wp_supsystic_tbl_diagrams        |
| wp_supsystic_tbl_rows            |
| wp_supsystic_tbl_tables          |
| wp_term_relationships            |
| wp_term_taxonomy                 |
| wp_termmeta                      |
| wp_terms                         |
| wp_usermeta                      |
| wp_users                         |
| wp_wp_rp_tags                    |
| wp_wpfb_cats                     |
| wp_wpfb_files                    |
| wp_wpfb_files_id3                |
| wp_yoast_seo_links               |
| wp_yoast_seo_meta                |
+----------------------------------+
84 rows in set (0.00 sec)

Bây giờ chúng ta vào Server A xem có Table này chưa:

mysql> show tables;
+----------------------------------+
| Tables_in_web                    |
+----------------------------------+
| VnGeek                           |
| wp_bp_activity                   |
| wp_bp_activity_meta              |
| wp_bp_notifications              |
| wp_bp_xprofile_data              |
| wp_bp_xprofile_fields            |
| wp_bp_xprofile_groups            |
| wp_bp_xprofile_meta              |
| wp_cntctfrm_field                |
| wp_commentmeta                   |
| wp_comments                      |
| wp_comments_fbseo                |
| wp_cptch_images                  |
| wp_cptch_packages                |
| wp_cptch_whitelist               |
| wp_dprv_licenses                 |
| wp_dprv_post_content_files       |
| wp_dprv_posts                    |
| wp_email                         |
| wp_gdsr2_log                     |
| wp_gdsr2_multi                   |
| wp_gdsr2_multi_meta              |
| wp_gdsr2_multi_values            |
| wp_gdsr2_ratings                 |
| wp_gdsr2_ratings_meta            |
| wp_links                         |
| wp_microblogposter_accounts      |
| wp_microblogposter_items_meta    |
| wp_microblogposter_logs          |
| wp_microblogposter_old_items     |
| wp_microblogposter_user_accounts |
| wp_nxs_log                       |
| wp_oauth_access_tokens           |
| wp_oauth_authorization_codes     |
| wp_oauth_clients                 |
| wp_oauth_jwt                     |
| wp_oauth_public_keys             |
| wp_oauth_refresh_tokens          |
| wp_oauth_scopes                  |
| wp_options                       |
| wp_popularpostsdata              |
| wp_popularpostsdatacache         |
| wp_postmeta                      |
| wp_posts                         |
| wp_pppm_filter                   |
| wp_pppm_html                     |
| wp_pppm_polls                    |
| wp_pppm_polls_items              |
| wp_pppm_polls_votes              |
| wp_pppm_protocol                 |
| wp_pppm_shortcut                 |
| wp_rating_scores                 |
| wp_ratings                       |
| wp_relevanssi                    |
| wp_relevanssi_log                |
| wp_relevanssi_stopwords          |
| wp_revslider_css                 |
| wp_revslider_layer_animations    |
| wp_revslider_navigations         |
| wp_revslider_settings            |
| wp_revslider_sliders             |
| wp_revslider_slides              |
| wp_revslider_static_slides       |
| wp_signups                       |
| wp_smush_dir_images              |
| wp_ssubscribe_app                |
| wp_subscribers                   |
| wp_subscribers_log               |
| wp_supsystic_tbl_columns         |
| wp_supsystic_tbl_diagrams        |
| wp_supsystic_tbl_rows            |
| wp_supsystic_tbl_tables          |
| wp_term_relationships            |
| wp_term_taxonomy                 |
| wp_termmeta                      |
| wp_terms                         |
| wp_usermeta                      |
| wp_users                         |
| wp_wp_rp_tags                    |
| wp_wpfb_cats                     |
| wp_wpfb_files                    |
| wp_wpfb_files_id3                |
| wp_yoast_seo_links               |
| wp_yoast_seo_meta                |
+----------------------------------+
84 rows in set (0.00 sec)

Vâng và trên server A đã có Table VnGeek.

Chúng ta tiến hành xóa table VnGeek trên server A xem:

mysql> DROP TABLE VnGeek;

Vâng và trên server B đã biến mất table này:

mysql> show tables;
+----------------------------------+
| Tables_in_web                    |
+----------------------------------+
| wp_bp_activity                   |
| wp_bp_activity_meta              |
| wp_bp_notifications              |
| wp_bp_xprofile_data              |
| wp_bp_xprofile_fields            |
| wp_bp_xprofile_groups            |
| wp_bp_xprofile_meta              |
| wp_cntctfrm_field                |
| wp_commentmeta                   |
| wp_comments                      |
| wp_comments_fbseo                |
| wp_cptch_images                  |
| wp_cptch_packages                |
| wp_cptch_whitelist               |
| wp_dprv_licenses                 |
| wp_dprv_post_content_files       |
| wp_dprv_posts                    |
| wp_email                         |
| wp_gdsr2_log                     |
| wp_gdsr2_multi                   |
| wp_gdsr2_multi_meta              |
| wp_gdsr2_multi_values            |
| wp_gdsr2_ratings                 |
| wp_gdsr2_ratings_meta            |
| wp_links                         |
| wp_microblogposter_accounts      |
| wp_microblogposter_items_meta    |
| wp_microblogposter_logs          |
| wp_microblogposter_old_items     |
| wp_microblogposter_user_accounts |
| wp_nxs_log                       |
| wp_oauth_access_tokens           |
| wp_oauth_authorization_codes     |
| wp_oauth_clients                 |
| wp_oauth_jwt                     |
| wp_oauth_public_keys             |
| wp_oauth_refresh_tokens          |
| wp_oauth_scopes                  |
| wp_options                       |
| wp_popularpostsdata              |
| wp_popularpostsdatacache         |
| wp_postmeta                      |
| wp_posts                         |
| wp_pppm_filter                   |
| wp_pppm_html                     |
| wp_pppm_polls                    |
| wp_pppm_polls_items              |
| wp_pppm_polls_votes              |
| wp_pppm_protocol                 |
| wp_pppm_shortcut                 |
| wp_rating_scores                 |
| wp_ratings                       |
| wp_relevanssi                    |
| wp_relevanssi_log                |
| wp_relevanssi_stopwords          |
| wp_revslider_css                 |
| wp_revslider_layer_animations    |
| wp_revslider_navigations         |
| wp_revslider_settings            |
| wp_revslider_sliders             |
| wp_revslider_slides              |
| wp_revslider_static_slides       |
| wp_signups                       |
| wp_smush_dir_images              |
| wp_ssubscribe_app                |
| wp_subscribers                   |
| wp_subscribers_log               |
| wp_supsystic_tbl_columns         |
| wp_supsystic_tbl_diagrams        |
| wp_supsystic_tbl_rows            |
| wp_supsystic_tbl_tables          |
| wp_term_relationships            |
| wp_term_taxonomy                 |
| wp_termmeta                      |
| wp_terms                         |
| wp_usermeta                      |
| wp_users                         |
| wp_wp_rp_tags                    |
| wp_wpfb_cats                     |
| wp_wpfb_files                    |
| wp_wpfb_files_id3                |
| wp_yoast_seo_links               |
| wp_yoast_seo_meta                |
+----------------------------------+
83 rows in set (0.00 sec)

Như vậy qua bao nhiêu khó khăn và vất vả chúng ta đã thiết lập xong đồng bộ cơ sở dữ liệu giữa server A và server B rồi.

Bình luận