Nội dung text: Phát triển ứng dụng web với server - side javascript
ĐẠI HỌC QUỐC GIA HÀ NỘI
TRƢỜNG ĐẠI HỌC CÔNG NGHỆ
Nguyễn Tuấn Dũng
PHÁT TRIỂN ỨNG DỤNG WEB VỚI
SERVER – SIDE JAVASCRIPT
KHÓA LUẬN TỐT NGHIỆP ĐẠI HỌC CHÍNH QUY
Ngành: Công nghệ Thông tin
HÀ NỘI – 2012
ĐẠI HỌC QUỐC GIA HÀ NỘI
TRƢỜNG ĐẠI HỌC CÔNG NGHỆ
Nguyễn Tuấn Dũng
PHÁT TRIỂN ỨNG DỤNG WEB VỚI
SERVER – SIDE JAVASCRIPT
KHÓA LUẬN TỐT NGHIỆP ĐẠI HỌC CHÍNH QUY
Ngành: Công nghệ Thông tin
Cán bộ hƣớng dẫn: TS Nguyễn Hải Châu
HÀ NỘI – 2012
LỜI CẢM ƠN
Lời đầu tiên, tôi xin gửi lời cảm ơn sâu sắc nhất tới Tiến sĩ Nguyễn Hải Châu,
ngƣời đã tận tình hƣớng dẫn và giúp đỡ tôi trong suốt quá trình thực hiện khóa luận tốt
nghiệp.
Tôi chân thành cảm ơn các thầy, cô đã tạo những điều kiện thuận lợi cho tôi học
tập và nghiên cứu tại trƣờng Đại học Công nghệ. Các thầy cô đã giảng dạy và cho tôi
những kiến thức quý báu, làm nền tảng để tôi hoàn thành khóa luận cũng nhƣ công việc
trong tƣơng lai.
Tôi cũng xin gửi lời tri ân tới các bạn trong lớp K53CC đã ủng hộ và giúp đỡ tôi
trong suốt quá trình học tập tại trƣờng.
Cuối cùng, tôi muốn gửi lời cảm ơn vô hạn tới gia đình và bạn bè – những ngƣời
thân yêu luôn ở bên, khuyến khích và động viên tôi trong cuộc sống cũng nhƣ trong học
tập.
Tôi xin chân thành cảm ơn.
Hà nội, tháng 5 năm 2012
Sinh viên
Nguyễn Tuấn Dũng
PHÁT TRIỂN ỨNG DỤNG WEB VỚI SERVER-SIDE JAVASCRIPT
Nguyễn Tuấn Dũng
Khóa QH-2008-I/CQ, ngành Công nghệ thông tin
Tóm tắt Khóa luận tốt nghiệp:
Ngày nay với kỉ nguyên công nghệ bùng nổ, thời kì của mạng xã hội đã khiến cho số lƣợng
ngƣời dùng truy cập vào cùng một hệ thống ngày càng tăng.Điển hình nhƣ Facebook một ngày
phục vụ hơn 1000 tỉ lƣợt xem với khoảng hơn 800 triệu lƣợt khách vào ra trong một tháng thì ta
mới hình dung đƣợc sự bùng nổ của thông tin nhƣ thế nào.Để giải quyết vấn đề bùng nổ nhƣ trên
thì chúng ta đã mở rộng các hệ thống máy chủ siêu lớn, phân thành nhiều các cụm đặt khắp nơi
trên thế giới.Nhƣng với tốc độ tăng trƣởng theo cấp số hiện nay thì việc tăng số lƣợng máy chủ
lên thôi có lẽ không đủ.Ta cần xem xét và nâng cấp các giải pháp xây dựng web cho tƣơng lai.
Đầu tiên là về mặt ngôn ngữ và máy chủ.Các websever hiện hay với cách truyền thống là
phục vụ theo luồng tự nó đã giới hạn khả năng của các máy chủ cho việc đáp ứng số lƣợng yêu
cầu đến từ ngƣời dùng và không tốt cho các bài toàn cần tính toán thời gian thực.Giải pháp
hƣớng sự kiện của nodeJS có vẻ khả khi trong trƣờng hợp này.Nó sẽ giảm số luồng hoạt động
của máy chủ xuống, giảm thời gian trễ nên đáp ứng rất tốt các ứng dụng thời gian thực.Ngoài ra
việc tận dụng tốt hơn sẽ khiến cho số truy vấn đến nhiều hơn khiến cho việc giảm thiểu số máy
chủ xuống.
Thứ hai là về mặt cơ sở dữ liệu.Với các hệ thống với số lƣợng lên đến hàng triệu cho đến
hàng tỉ thì việc hiệu năng tốt là việc bắt buộc.Hệ thống máy chủ cơ sở dữ liệu đòi hỏi phải rất
mạnh mẽ nếu không máy chủ sẽ bị quá tải.Với các hệ RBDMs hiện nay thì vấn đề hiệu năng
thƣờng không tốt cho trƣờng hợp này.Ngôn ngữ SQL là ngôn ngữ thông dịch với các ràng buộc
trong các bảng khiến cho hiệu năng thực sự của hệ thống cơ sở dữ liệu khi thực thi là khá ì ạch
với hệ thống lớn nhƣ kể trên.Chƣa kể là với hệ thống lớn thì vấn đề phân tán dữ liệu, tính toàn
vẹn dữ liệu là việc rất quan trọng.NoSQL đáp ứng đƣợc tất cả các yêu cầu này.Với tốc độ nhanh
do không phải qua các câu truy vấn SQL, có tính sẵn sàng, phân tán cao và độ ổn định tuyệt
vời.Rất thích hợp cho các hệ thống có lƣợt truy vấn lớn.Ở trong khóa luận của tôi, tôi sẽ nghiên
cứu về một NoSQL khá phổ biến - CouchDB.Với khả năng chịu lỗi tốt và tính ổn định cao, đồng
bộ giữa các thiết bị tốt, hỗ trợ các phiên bản khi offline tốt.CouchDB xứng đáng là một cơ sở dữ
liệu đáng tin cậy.
Từ khóa: Nodejs, javascript server side, nosql, couchdb
LỜI CAM ĐOAN
Tôi xin cam đoan đây là công trình nghiên cứu và thực hiện khóa luận thực sự của
riêng tôi, dƣới sự hƣớng dẫn của ThS Nguyễn Hải Châu
Mọi tham khảo từ các tài liệu, công trình nghiên cứu liên quan trong nƣớc và quốc
tế đều đƣợc trích dẫn rõ ràng trong luận văn. Mọi sao chép không hợp lệ, vi phạm quy
chế hay gian trá tôi xin hoàn toàn chịu trách nhiệm và chịu mọi kỷ luật của ĐHQG Hà
Nội và Nhà trƣờng.
Hà Nội, ngày 18 tháng 05 năm 2012
Sinh viên
Nguyễn Tuấn Dũng
MỤC LỤC
MỞ ĐẦU ....................................................................................................................................... 1
CHƢƠNG 1: TÌM HIỂU VỀ NODE WEB: NODE.JS – THƢ VIỆN VIẾT ỨNG DỤNG
SERVER-SIDE JAVASCRIPT ...................................................................................................... 2
1.1. Javascript và lập trình server ............................................................................................. 2
1.2. NodeJs là gì? ...................................................................................................................... 2
1.3. Khác nhau giữa Blocking và Non-Blocking ..................................................................... 3
1.3.1. Blocking ..................................................................................................................... 3
1.3.2. Non-Blocking ............................................................................................................. 4
1.3.3. Lợi ích even-driven so với lại tốt hơn thread-driven.................................................. 4
1.4. Node package manager (NPM) ......................................................................................... 7
1.4.1 Giới thiệu về NPM ...................................................................................................... 7
1.4.2. Định dạng một gói cài npm ........................................................................................ 7
1.4.3. Sử dụng npm ............................................................................................................... 8
1.4.4. Gói toàn cục và gói cục bộ trong khi npm cài đặt ...................................................... 9
Chƣơng 2 TÌM HIỂU VỀ CÁC GIẢI PHÁP CƠ SỞ DỮ LIỆU DẠNG NOSQL (NOT
ONLY SQL) ................................................................................................................................. 10
2.4 Đặc điểm của NoSQL? .................................................................................................... 11
2.5 Phân loại NoSQL? ............................................................................................................ 12
2.5.1. Wide Column Store / Column Families ................................................................... 12
2.5.2. Key-Value Store/Tuple store .................................................................................... 12
2.5.3. Document Store ........................................................................................................ 12
2.5.4. Graph Database ........................................................................................................ 13
2.6 Hiệu năng NoSQL ........................................................................................................... 13
2.6.1. Xử lý việc suy giảm hiệu năng ..................................................................................... 13
2.6.2. Xử lý một dữ liệu cực lớn ............................................................................................. 14
2.7. Các loại NoSQL phổ biến ................................................................................................ 15
2.7.1. MongoDB [2][3] ....................................................................................................... 15
2.7.2. CouchDB [4] ............................................................................................................ 16
2.7.3. Cassandra[5] ............................................................................................................. 17
2.7.4. Membase [6] ............................................................................................................. 19
Chƣơng 3 TÌM HIỂU VỀ COUCHDB ....................................................................................... 20
3.1. CouchDB là gì ................................................................................................................. 20
3.2. Lịch sử CouchDB ............................................................................................................ 20
3.3. Các đặc điểm của CouchDB ............................................................................................ 20
3.3.1. Document storage ..................................................................................................... 21
3.3.2. Map/Reduce Views và Indexes ................................................................................ 21
3.3.3. Kiến trúc phân tán với việc nhân bản [10] [11] ........................................................ 21
3.3.4. REST API ................................................................................................................. 22
3.3.5. Tính nhất quán cuối cùng. ........................................................................................ 23
3.3.6. Sử dụng Offline ........................................................................................................ 23
3.4. Sử dụng CouchDB ........................................................................................................... 23
3.4.1. Khởi động ................................................................................................................. 23
3.4.2. Xử lý truy vấn trong CouchDB ................................................................................ 23
3.4.3. Views ........................................................................................................................ 24
3.4.6. Futon ............................................................................................................................. 28
3.5. Tìm hiểu phần mở rộng GEO của COUCHDB ............................................................... 29
3.5.1. GeoCouch là gì ......................................................................................................... 29
3.5.2. Cài đặt GeoCouch..................................................................................................... 30
3.5.3. Kết nối NodeJs và GeoCouch .................................................................................. 31
3.5.4. Sử dụng GeoCouch................................................................................................... 31
Chƣơng 4 ỨNG DỤNG MAPCHAT ........................................................................................... 33
4.1. ExpressJS ......................................................................................................................... 33
4.2. SocketIO .......................................................................................................................... 34
4.3. Cài đặt project .................................................................................................................. 35
4.3.1. Phần Chatting ........................................................................................................... 35
4.3.2 Phần map ................................................................................................................... 36
KẾT LUẬN ................................................................................................................................. 39
DANH SÁCH CÁC BẢNG
Bảng 1: So sánh CSDL quan hệ và NoSQL………………………………………..11
Bảng 2: Bảng tƣơng ứng các câu lệnh truy vấn ……...……………………………23
DANH SÁCH CÁC HÌNH VẼ
Hình 1:Bảng so sánh hiệu n……………………………………………………….13
Hình 2: Giao diện Futon……………………………………………………………28
Hình 3: Tạo temporary view……………………………………………………….29
Hình 4: Ứng dụng mapchat………………………………………………………...38
DANH SÁCH CÁC TỪ VIẾT TẮT
Từ viết tắt Nghĩa của từ viết tắt
SQL Structured Query Language
API Application on Programming Interface
ACID Atomicity, Consistency, Isolation, Durability
CSDL Cơ sở dữ liệu
MỞ ĐẦU
Ngày nay với kỉ nguyên công nghệ bùng nổ, thời kì của mạng xã hội đã khiến cho số
lƣợng ngƣời dùng truy cập vào cùng một hệ thống ngày càng tăng. Điển hình nhƣ
Facebook một ngày phục vụ hơn 1000 tỉ lƣợt xem với khoảng hơn 800 triệu lƣợt khách
vào ra trong một tháng thì ta mới hình dung đƣợc sự bùng nổ của thông tin nhƣ thế nào.
Để giải quyết vấn đề bùng nổ nhƣ trên thì chúng ta đã mở rộng các hệ thống máy chủ siêu
lớn, phân thành nhiều các cụm đặt khắp nơi trên thế giới. Nhƣng với tốc độ tăng trƣởng
theo cấp số hiện nay thì việc tăng số lƣợng máy chủ lên thôi có lẽ không đủ. Ta cần xem
xét và nâng cấp các giải pháp xây dựng web cho tƣơng lai.
Chƣơng 1: Tìm hiểu về node web: node. js – Thƣ viện viết ứng dụng server-side
javascript. Giới thiệu cho chúng ta tổng quan về một thƣ viện mới đƣợc viết bằng
javascript có khả năng chạy đƣợc trên server. Chúng ta sẽ giới thiệu qua về cách hoạt
động, các đặc điểm của nó và điểm mạnh điểm yếu của bộ thƣ viện này.
Chƣơng 2: Tìm hiểu về các giải pháp CSDL dạng NoSQL (Not-Only-SQL).
Chƣơng này giới thiệu cho chúng ta tổng quan về khái niệm NoSQL, các đặc điểm nổi bật
của nó. So sánh tƣơng quan giữa NoSQL và SQL truyền thống. Từ đó đƣa ra đƣợc các
giải pháp cho các trƣờng hợp nào nên dùng NoSQL.
Chƣơng 3: Tìm hiểu về CouchDB. Chƣơng này giới thiệu về một NoSQL khá phổ
biến hiện nay - CouchDB. Nêu ra đặc điểm, điểm yếu mạnh và cách dùng cơ bản của nó.
Chƣơng 4: Tìm hiểu phần mở rộng GEO của CouchDB. Trong phần này chúng ta
sẽ tìm hiểu về một phần mở rộng của CouchDB có khả năng hỗ trợ các định dạng địa lý
nhƣ điểm, vecto ... v..v đó là GeoCouch.Sẽ hƣớng dẫn cách dùng và cách sử dụng cơ bản
của nó
Kết luận: NoSQL và Javscript server side có thể sẽ là tƣơng lai của web trong một
tƣơng lai không xa. Khi mà yêu cầu về tốc độ, thống nhất ngôn ngữ, tính sẵn sàng và khả
năng mở rộng cao đƣợc đặt lên hàng đầu
1
CHƢƠNG 1: TÌM HIỂU VỀ NODE WEB: NODE.JS – THƢ VIỆN VIẾT ỨNG
DỤNG SERVER-SIDE JAVASCRIPT
1.1. Javascript và lập trình server
Mặc dù các ứng dụng trên nền web chở nên phổ biến trong những năm gần đây,
nhƣng chúng vẫn rất khó để phát triển, duy trì và mở rộng. Nhiều thách thức ở đây là việc
ngăn cách giữa các thành phần client và server. Các thành phần phía client thƣờng đƣợc
sử dụng bao gồm HTML, CSS, Javascript, Ajax(một phần của javascript), ảnh và các file
mà ta có thể tải về từ trình duyệt. Phía server, thì ta cần lắng nghe từ các yêu cầu, xuất ra
tài nguyên hoặc thông tin và thao tác với chúng để chúng có thể gửi trả về phía client.
Điều này thƣờng đƣợc thực hiện bằng cách sử dụng XML, JSON hoặc là định dạng theo
kiểu HTML, cái mà gửi thông qua đƣờng truyền sử dụng Ajax. Ta có vô số các công nghệ
cạnh tranh đƣợc chọn ở đây. Phụ thuộc vào đƣờng truyền, phần cứng, hệ điều hành, băng
thông, chuyên môn công nghệ và vô vàn các yếu tố khác. Mỗi một công nghệ mang lại
một trải nghiệm khác nhau. Các ngôn ngữ phía server đƣợc dùng phổ biến đến bây giờ là
PHP, java và .NET.
Điều này dẫn đến việc cần có một chuẩn để thống nhất lập trình giữa server và
client. Và phong trào ServerJS với mục đích ra xóa bỏ hàng rào ngăn cách giữa client và
server. Họ tìm cách giữ lại các thành phần chủ đạo và tìm điểm chung cho client và
server. Các thành phần đƣợc giữ lại là HTML, javscript và CSS, cái mà đã quá quen thuộc
với ngƣời dùng cuối. Còn về phía server. Họ xây dựng server dựa theo Javascript có thể
làm web server và nhiều hơn thế nữa. Rất nhiều dịch vụ server đƣợc viết bằng JavaScript
đã ra đời ví dụ nhƣ Jaxer đƣợc phát triển bởi Aptana, Jaxer là một web serve dựa Ajax
để xây dựng một trang web nhiều tính năng cũng nhƣ các ứng dụng sử dụng mô hình ajax
cái có thể đƣợc viết hoàn toàn bằng JavaScirpt
Chúng ta sẽ tập trung vào một Javascript-server-side khác: Nodejs
1.2. NodeJs là gì?
Javascript trƣớc đây chỉ chạy đƣợc trên trình duyệt web. Nhƣng gần đây nó đƣợc
dùng ở phía server. Có những môi trƣờng Javascript ở phía server nhƣ là Jaxer và
Narwhal, tuy nhiên Nodejs có một chút khác biệt so với những cái trên. Bởi vì nó dựa trên
sự kiện hơn là dựa theo luồng (thread). Các máy chủ Web nhƣ Apache thƣờng sử lý PHP
và các script CGI khác dựa theo luồng bởi chúng sinh ra một hệ thống luồng cho mỗi
request đến. Trong khi cách đó là ổn cho rất nhiều ứng dụng thì các mô hình dựa theo
2
luồng không thể mở rộng một cách có hiệu quả với nhiều kết nối tồn tại lâu. Ví dụ nhƣ
bạn muốn dùng các dịch vụ thời gian thực nhƣ Friendfeed hay Google Wave.
Nodejs, sử dụng một sự kiện lặp thay cho các luồng, và nó có thể mở rộng lên hàng
triệu kết nối một lúc. Điều này rất có lợi vì thực tế các máy chủ sử dụng phần lớn thờti
gian vào việc đợi các xử lý vào ra (ví dụ nhƣ đọc một file từ ổ cứng, truy vấn đến một
dịch vụ web bên ngoài hoặc là đợi file đƣợc tải lên hoàn tất) bởi vì các xử lý đó chậm
hơn rất nhiều so với xử lý bộ nhớ. Với kiến trúc hƣớng sự kiện thì lƣợng bộ nhớ dùng ít
hơn, lƣu nƣợng tăng cao và mô hình lập trình thì đơn giản hơn.
Mỗi một xử lý vào ra trong Nodejs là không đồng bộ, nghĩa là máy chủ có thể tiếp
tục sử lý các request đến trong khi các sử lý vào ra đang diễn ra. Javascript mà một ngôn
ngữ phù hợp cho việc lập trình hƣớng sự kiện bởi vì nó có các hàm không đồng bộ và sự
bao đống cái mà tạo ra một hàm callbacks đảm bảo. Và lập trình viên Javascript thì đã
biết cách lập trình theo cách này rồi. Mô hình hƣớng sự kiện khiến cho Nodejs chạy rất
nhanh và có thể triển khai và mở rộng cho các ứng dụng thời gian thực một cách dễ dàng.
Một lợi ích lớn lao của NodeJS đó là nó đƣợc viết bằng javascript. Nó cũng hỗ trợ
các hệ NoSQL dùng javascript để truy vấn. Từ đây ta chỉ cần học một ngôn ngữ là
javascript để thực thi từ phía trình duyệt, phía webserver và cả cho database server.
1.3. Khác nhau giữa Blocking và Non-Blocking
1.3.1. Blocking
Theo cách truyền thống (thread-based) thì hãy tƣởng tƣợng một ngân hàng đang áp
dụng mô hình phục vụ:Phục vụ hoàn toàn một yê u cầu rồi mới chuyển sang yêu cầu
khác. Trong đó nhân viên trong ngân hàng. Tƣơng ứng mỗi nhân viên là một Thread. Và
mỗi một yêu cầu tƣơng ứng là 1 request đến server. Bạn yêu cầu là muốn gửi tiền vào
ngân hàng. Bạn sẽ phải điền 1 số form nhƣ tên ngƣời gửi, số tài khoản của họ, số tiền cần
gửi. v...v. Trong thời gian bạn điền thông tin cần rút tiền vào tờ khai. Cô nhân viên phải
chờ bạn. Bạn đã "khóa" cô ấy không cho cô ấy phục vụ các khách hàng khác vì lúc đó cô
ấy đang rảnh vì phải đợi bạn. Hành động đợi ở đây phần lớn là hành động vào/ra, truy
suất file, hoặc đợi kết quả truy vấn SQL trong Webservice. Đó là cơ chế Blocking.
Theo cách này. Nếu ngân hàng đang quá tải vì có quá nhiều ngƣời chờ đƣợc phục
vụ. Thì ngân hàng chỉ còn một cách duy nhất là. Tăng thêm số nhân viên phục vụ lên. Ở
trƣờng hợp này trong ví dụ chúng ta là tăng số server phục vụ lên.
3
Vấn đề xảy ra ở đây ra. Khi tăng số lƣợng nhân viên lên để đáp ứng nhu cầu phục vụ
khách hàng thì ngân hàng phải tăng chi phí (tiền để trả lƣơng, mặt bằng văn phòng...)
(tƣơng ứng với việc tăng phần cứng máy chủ lên để đáp ứng). Nhƣ thế sẽ gây ra các vấn
đề về lãng phí. Và không tận dụng đƣợc nguồn lực và tiết kiệm đƣợc chi phí
1.3.2. Non-Blocking
Ở một ngân hàng khác, họ lại áp dụng theo một phƣơng thức mới (event-
driven):Tận dụng mọi khả năng của tất cả các nhân viên khi họ rảnh và nhân viên khi có
yêu cầu mới phục vụ.Tức là khi bạn có một yêu cầu muốn gửi tiền nhƣ ở trên. Cô nhân
viên chỉ cần đƣa bạn bút và giấy để bạn điền vào và bảo bạn hãy ngồi ở ghế chờ để điền
xong thông tin gửi tiền. Trong khi đó cô ấy có thể phục vụ những vị khách tiếp theo. Ở
đây bạn đã không "khóa" cô ấy lại. Và cô nhân viên tranh thủ lúc đợi bạn điền các thông
tin. Cô ấy có thể làm việc khác. Thành ra ở đây không có hành động đợi vô nghĩa ở đây.
Khi bạn điền xong thông tin, bạn có thể trở lại gặp cô ấy báo là đã hoàn thành. Cô ấy sẽ
tiếp tục phục vụ bạn để bạn hoàn thành việc của mình. Đây là cơ chế Non-Blocking.
Bạn có thể thấy, theo mô hình áp dụng của ngân hàng này (event-driven), họ sẽ tận
dụng đƣợc khoảng thời gian rỗi của nhân viên. Khiến cho việc một nhân viên có thể phục
vụ nhiều khách hàng hơn so với ngân hàng dùng mô hình theo cách cũ ở trên. Nếu có quá
tải. Bạn chắc chắn vẫn phải thêm nhân viên để đáp ứng kịp thời. Nhƣng chắc chắn sẽ
thêm ít nhân viên hơn. Tiết kiệm đƣợc rất nhiều tài nguyên. (Đây cũng là mô hình đƣợc
áp dụng phổ biến ở các ngân hàng).
1.3.3. Lợi ích even-driven so với lại tốt hơn thread-driven
Nói đến đây, chắc chắn sẽ có một vài câu hỏi đƣợc đặt ra:
- Mặc định, Nodejs chỉ có một luồng đƣợc thực thi. Nó không cần đợi các tác vụ
vào ra hoặc là chuyển nội dung. Thay vào đó, các tác vụ vào/ra sẽ tự động tạo
ra một hàm điều khiển gửi tới các sự kiện khi mà mọi thứ đã xong. Các sự kiện
lặp và mô hình điều hƣớng lặp cũng giống nhƣ cách mà javascript ở phía trình
duyệt thực hiện. Chƣơng trình sẽ xử lý các hành động và nhanh chóng quay về
vòng lặp để gửi các tác vụ khác đến. Khi load 1 trang và đang chờ nó truy xuất
cơ sở dữ liệu, thì nodejs sẽ tranh thủ phục vụ request khác. Trong khi việc chờ
truy xuất cơ sở dữ liệu vẫn tiếp tục. Vậy cũng thể coi đó là 2 tiến trình hoàn
tòan khác nhau.
4
- Ngay trong hệ điều hành đã áp dụng mô hình dựa theo sự kiện (event-based)
rồi. Nó sẽ không chỉ có 1 thread mà sẽ có rất nhiều thread. Và khi 1 thread tiến
trình đang bị blocking I/O. Thì hệ điều hành sẽ cho các thread khác đƣợc chạy
thay thế. Và nhƣ thế sẽ không có thời gian trễ. Nhƣ vậy sẽ không có lợi ích gì
đáng kể của mô hình hƣớng sự kiện so với không hƣớng sự kiện.
Có thể trả lời 2 câu hỏi trên nhƣ sau bằng 1 ví dụ: (Ở đây ta sẽ so sánh Nodejs với
Apache)
1 đoạn code sau:
result = query( "select A from B" );
do_something(result);
Theo cách thông thƣờng nhƣ trên. Nếu một request đƣợc gửi đến yêu cầu xử lý đoạn
code trên. Webservice sẽ phải tạo ra 1 thread để xử lý. Vấn đề là thread đƣợc tạo ra đó sẽ
không làm gì cả trong khi hàm query() vẫn đang chạy. Cho đến khi kết quả của câu lệnh
truy vấn SQL trên xử lý thành công, lâu hay nhanh thì tùy thuộc vào độ phức tạp của câu
truy vấn. Sau đó thread sẽ gọi hàm do_something. Đó thực sự không tốt bởi vì trong khi
toàn bộ các tiến trình đang trong trạng thái đợi(trừ tiến trình SQL) thì các yêu cầu mới
vẫn tiếp tục đƣợc gửi đến. Lúc này sẽ sinh ra rất nhiều các tiến trình đang đợi thực thi câu
lệnh, theo đúng cơ chế Blocking, vẫn ngốn tài nguyên máy chủ nhƣng không làm gì cả.
Và nếu tất cả các tiến trình nhiều đến mức ngốn hết tài nguyên trong khi các tác vụ vẫn
chƣa xong vì phải đợi thì lúc đó hệ thống sẽ sụp đổ. Quả thực là rất lãng phí. Mà việc
chuyển trạng thái giữa các tiến trình là luôn có một khoảng thời gian trễ nào đó, mà càng
nhiều tiến trình thì CPU càng mất nhiều thời gian để lƣu trữ và khởi động lại các trạng
thái, kéo theo tổng thời gian trễ đợi chuyển giữa các tiến trình là tăng lên. Đơn giản bằng
cách không đồng bộ, Node sẽ tận dụng triệt để tài nguyên do không có tài nguyên nào
phải đợi lãng phí nữa.
Một điểm yếu của lập trình hƣớng luồng là việc đồng bộ và tính đồng nhất của nó.
Độ phức tạp của nó đến từ việc trao đổi giữa các biến và các hàm để tránh việc deadlock
và xung đột giữa các luồng với nhau.
Node khiến cho chúng ta phải hiểu theo một nghĩa khác thế nào là đồng nhất. Các
hàm callback đƣợc gọi một cách không đồng bộ trong các sự kiện lặp xử lý khá tốt trong
việc đồng nhất, khiến cho mô hình đồng nhất trở nên đơn giản hơn, dễ hiễu hơn và dễ
5
thực hiện hơn. Nhất là khi với việc trễ trong truy xuất các đối tƣợng. Nếu truy suất trong
bộ nhớ thì ta chỉ mất với thời gian là nano giây, truy suất đĩa cứng hoặc qua mạng cục bộ
thì có thể mất thời gian là mili giây hoặc thậm trí cả giây. Nhƣng việc truy suất đó chƣa
hẳn đã xong, sẽ còn khá nhiều các tác vụ khác nữa trƣớc khi đƣợc đƣa đến ngƣời dùng
cuối, họ sẽ phải chờ rất nhiều thời gian để kết quả có thể hiện ra.
Còn với NodeJs thì câu truy vấn sẽ nhƣ thế này:
query(statement: "select A from B",
function(result){
// Xu ly ket qua sau khi tra ve
do_something();
} );
Theo cách viết dƣới thì nó, tức nodejs, sẽ báo cho môi trƣờng hoạt động (ở đây là
OS và webserver) là khi nào cần tạo tiến trình và phải làm gì. Đơn giản ở trên đoạn viết
trên, chƣơng trình vẫn sẽ tạo ra một thread và sẽ báo là khi nếu có câu truy vấn query() thì
chƣơng trình sẽ đợi hàm đó chạy xong. Trong lúc đợi query() chạy nó có thể phục vụ các
truy vấn khác. Khi nào query() truy vấn cơ sở dữ liệu xong. Chƣơng trình sẽ quay trở lại
gọi lại hàm callback ở trên là do_something(). Do đó, thread đó sẽ không phải đợi. Việc
tính toán giữa nhiều request có thể thực hiện một cách song song.
Cách viết code ở trên thực hiện y hệt nhƣ code ở phía trƣớc nữa thực hiện. Chỉ có
điểm khác biệt là kết quả của việc truy vấn không phải là trả về kết quả truy vấn mà là trả
về 1 hàm callback sẽ đƣợc thực thi sau khi truy vấn đƣợc thực thi hoàn toàn. Lúc này khi
sau khi truy vấn đƣợc thực thi xong.Ta có thể toàn quyền xử lý với kết quả trả về, đặt
thêm các sự kiện khác đến với nó. Ta có thể thấy event-driven khá giống với lập trình
socket .
Tóm lại, sức mạnh của nodejs không dựa vào vòng lặp bắt sự kiện của nó hoặc là
đồng bộ vào/ra mà lại dựa vào hệ thống callback của nó đã làm giảm rất nhiều thời gian
chờ của hệ thống.
6
1.4. Node package manager (NPM)
1.4.1 Giới thiệu về NPM
Đƣợc viết tắt bởi Node Package Manager (Trình quản lý gói của nodejs). Nó vừa là
một trình quản lý gói vừa là một hệ thống phân tán phục vụ cho NodeJs. Mục đích chính
của nó là tạo ra và phân phối các gói Node, các module qua internet sử dụng dòng lệnh.
Với npm chúng ta có thể dễ dàng tìm các module một cách tự động qua mạng. Chỉ với
một câu lệnh, ta có thể tải, cài và sử dụng các module.
1.4.2. Định dạng một gói cài npm
Một gói cài npm miêu tả trúc thƣ mục của nó ở trong file package.json. Nó bao gồm
tên gói, phiên bản, cấu trúc các cấp của thƣ mục bên trong gói cài, các module nào cần
thiết, phụ thuộc cần phải cài trƣớc.
Một file package.json đơn giản nhất sẽ có cấu trúc nhƣ dƣới:
{ name: "PackageA",
version: "1.0",
main: "mainModuleName",
modules: {
"module1": "abc/module1",
"module2": "abc/module2"
}
}
Hai thẻ quan trọng nhất trong file này là thẻ name và thẻ version. Thẻ name sẽ miêu
tả tên của gói và đƣợc dùng để tìm gói dễ dàng hơn.
#npm search packageName
Ở đây package name chính là tên trong thẻ name. Thẻ version là thẻ khai báo tên
phiên bản của gói cài. Mặc định npm nếu không có các tham số nó sẽ tải gói cài với phiên
bản mới nhất
7
Trong một module trong NodeJs cũng có thể đi kèm các module phụ thuộc nó. Khai
báo trong file json thì npm sẽ tự động cài các module khác đi kèm với module đó. Khai
báo các gói phụ thuộc nhƣ sau
"dependencies":
{
"one": "1.0 - 2.5"
"two": ">= 0.9 <2.3"
}
Ngoài ra còn các tham số khác:
"description": "module của tôi"
"homepage" : "http://localhost"
"author" dung_b1991
1.4.3. Sử dụng npm
Mặc định npm tìm các gói từ trên Internet và chính xác hơn là từ trang chủ
http://npmjs.org. Nếu biết rõ tên module thì ta dùng câu lệnh sau:
#npm install moduleName
Nhƣng nếu bạn không nhớ đầy đủ tên module mà chỉ nhớ một phần tên thì sao.
Ngoài việc vào trang http://search.npmjs.org thì bạn có thể dùng npm để cài.
#npm search key_name
Sau khi cài đặt module, để tìm kiếm tài liệu hƣớng dẫn, trang chủ của module đó,
hoặc thông tin chi tiết về module này thì ngoài việc vào file package.json của chính
module đó, ta có thể dùng npm:
#npm view moduleName
Nếu muốn tìm chi tiết hơn ví dụ là tìm trang chủ hay phiên bản của module:
#npm view moduleName version
8
1.4.4. Gói toàn cục và gói cục bộ trong khi npm cài đặt
Mặc định khi dùng câu lệnh install trong npm sẽ là cài 1 gói ở dạng local, tức là nó
chỉ có tác dụng trên thƣ mục mình cài
Ví dụ tại thƣ mục nodejs/dirA/ có gói là testcase
cd nodejs/dirA/
npm install testcase
Trong thƣ mục nodejs/dirB/ ta tạo 1 file.js có gọi gói testcase
var HTTPServer = require('testcase');
Thì sẽ báo lỗi không tìm thấy gói testcase, vì gói testcase ta install nó trong thƣ mục
dirA, nên npm sẽ hiểu testcase là gói cục bộ trong thƣ mục dirA.
Để có thể dùng gói testcase trong dirB ta có thể dùng 2 cách sau:
Cục bộ:Ta vào lại thƣ mục dirB và cài lại gói testcase bằng npm, lúc
đó gói testcase sẽ là gói cục bộ trong thƣ mục dirB.
cd anotherapp/
npm install http-server
Toàn cục:Ta sẽ cài gói testcase là 1 gói toàn cục. Tức là bất cứ thƣ
mục nào (kể cả không phả dirA và dirB cũng có thể gọi gói testcase đƣợc.
#npm install http-server -g
Mặc định thì npm cài thêm module theo cách cục bộ tức là nó sẽ cài vào mục
node_modules tại thƣ mục hiện thời. Để thay đổi việc cài module sao cho khi cài npm sẽ
mặc định sẽ cài vào toàn cục. Đây là cách mà các chƣơng trình có thể dùng các module
toàn cục mà không cần cài thêm.
#npm set global=true
Để kiểm tra xem biến global đã đƣợc set chƣa. ta dùng tham số get
#npm get global
9
Chƣơng 2 TÌM HIỂU VỀ CÁC GIẢI PHÁP CƠ SỞ DỮ LIỆU DẠNG NOSQL
(NOT ONLY SQL)
2.1 NoSQL là gì ?
noSQL, viết tắt của non-relational, hoặc theo cách hiểu khác thì có nghĩa là Not only
SQL (không chỉ là SQL). NoSQL đặc biệt nhấn mạnh đến mô hình lƣu trữ cặp giá trị -
khóa và hệ thống lƣu trữ phân tán.
Hệ CSDL này có thể lƣu trữ, xử lý từ lƣợng rất nhỏ đến hàng petabytes dữ liệu với
khả năng chịu tải, chịu lỗi cao nhƣng chỉ đòi hỏi về tài nguyên phần cứng thấp. NoSQL
thiết kế đơn giản, nhẹ, gọn hơn so với RDBMs, thiết kế đặc biệt tối ƣu về hiệu suất, tác
vụ đọc-ghi, ít đòi hỏi về phần cứng mạnh và đồng nhất, dễ dàng thêm bớt các node
không ảnh hƣởng tới toàn hệ thống, …
2.2 So Sánh NoSQL và RDBM?
Các RDBMs hiện tại đã bộc lộ những yếu kém nhƣ việc đánh chỉ mục một lƣợng
lớn dữ liệu, phân trang, hoặc phân phối luồng dữ liệu media (phim, ảnh, nhạc, ...). Cơ
sở dữ liệu quan hệ đƣợc thiết kế cho những mô hình dữ liệu nhỏ thƣờng xuyên đọc viết
trong khi các Social Network Services lại có một lƣợng dữ liệu cực lớn và cập nhật liên
tục do số lƣợng ngƣời dùng quá nhiều ở một thời điểm. Thiết kế trên Distributed NoSQL
giảm thiểu tối đa các phép tính toán, I/O liên quan kết hợp với batch processing đủ đảm
bảo đƣợc yêu cầu xử lý dữ liệu của các mạng dịch vụ dữ liệu cộng đồng này. Facebook,
Amazon là những ví dụ điểm hình.
Về cơ bản, các thiết kế của NoSQL lựa chọn mô hình lƣu trữ tập dữ liệu theo cặp
giá trị key-value. Khái niệm node đƣợc sử dụng trong quản lý dữ liệu phân tán. Với các
hệ thống phân tán, việc lƣu trữ có chấp nhận trùng lặp dữ liệu. Một request truy vấn tới
data có thể gửi tới nhiều máy cùng lúc, khi một máy nào nó bị chết cũng không ảnh
hƣởng nhiều tới toàn bộ hệ thống. Để đảm bảo tính real time trong các hệ thống xử lý
lƣợng lớn, thông thƣờng ngƣời ta sẽ tách biệt database ra làm 2 hoặc nhiều database. Một
database nhỏ đảm bảo vào ra liên tục, khi đạt tới ngƣỡng thời gian hoặc dung lƣợng,
database nhỏ sẽ đƣợc gộp (merge) vào database lớn có thiết kế tối ƣu cho phép đọc (read
operation). Mô hình đó cho phép tăng cƣờng hiệu suất I/O - một trong những nguyên
nhân chính khiến performance trở nên kém.
2.3 Bảng so sánh
10