OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thứcChúng tôi đăng lại bản ghi chép báo cáo từ hội nghị HighLoad ++ 2016, được tổ chức tại Skolkovo gần Moscow vào ngày 7-8 tháng XNUMX năm ngoái. Vladimir Protasov cho biết cách mở rộng chức năng NGINX với OpenResty và Lua.

Xin chào mọi người, tôi tên là Vladimir Protasov, tôi làm việc cho Parallels. Tôi sẽ nói với bạn một chút về bản thân mình. Tôi dành ba phần tư cuộc đời để viết mã. Tôi đã trở thành một lập trình viên cốt lõi theo đúng nghĩa đen: đôi khi tôi nhìn thấy mã trong giấc mơ của mình. Một phần tư cuộc đời là phát triển công nghiệp, viết mã đi thẳng vào sản xuất. Code mà một số bạn dùng nhưng không biết.

Để cho bạn biết nó tồi tệ như thế nào. Khi tôi còn nhỏ, tôi đến và họ đưa cho tôi hai cơ sở dữ liệu terabyte này. Nó bây giờ ở đây cho tất cả mọi người tải cao. Tôi đến các hội nghị và hỏi: “Các bạn, hãy nói cho tôi biết, bạn có dữ liệu lớn không, mọi thứ có ổn không? Bạn có bao nhiêu căn cứ ở đó? Họ trả lời tôi: "Chúng tôi có 100 gigabyte!" Tôi nói: “Tuyệt, 100 gigabyte!” Và tôi tự nghĩ làm thế nào để giữ lại bộ mặt poker một cách gọn gàng. Bạn nghĩ, vâng, những người đó thật tuyệt, và sau đó bạn quay lại và mày mò với những cơ sở dữ liệu nhiều terabyte này. Và đây là một đàn em. Bạn có thể tưởng tượng những gì một hit nó là?

Tôi biết hơn 20 ngôn ngữ lập trình. Đây là những gì tôi đã phải tìm ra trong quá trình làm việc. Họ cung cấp cho bạn mã bằng Erlang, bằng C, bằng C ++, bằng Lua, bằng Python, bằng Ruby, bằng thứ gì đó khác và bạn phải cắt tất cả. Nói chung, tôi đã phải. Không thể tính toán con số chính xác, nhưng đâu đó khoảng 20 con số đã bị mất.

Vì mọi người ở đây đều biết Parallels là gì và chúng tôi làm gì, nên tôi sẽ không nói về việc chúng tôi ngầu như thế nào và chúng tôi làm gì. Tôi sẽ chỉ nói với bạn rằng chúng tôi có 13 văn phòng trên khắp thế giới, hơn 300 nhân viên, đang phát triển ở Moscow, Tallinn và Malta. Nếu muốn, bạn có thể lấy và chuyển đến Malta, nếu trời lạnh vào mùa đông và bạn cần sưởi ấm lưng.

Cụ thể, bộ phận của chúng tôi viết bằng Python 2. Chúng tôi đang kinh doanh và không có thời gian để giới thiệu các công nghệ thời thượng, vì vậy chúng tôi gặp khó khăn. Chúng tôi có Django, bởi vì nó có mọi thứ, và chúng tôi đã loại bỏ phần thừa và ném nó đi. Ngoài ra còn có MySQL, Redis và NGINX. Chúng tôi cũng có rất nhiều thứ hay ho khác. Chúng tôi có MongoDB, chúng tôi có những con thỏ chạy xung quanh, chúng tôi không có gì cả - nhưng nó không phải của tôi, và tôi không làm điều đó.

MởResty

Tôi kể về bản thân mình. Hãy xem những gì tôi sẽ nói về ngày hôm nay:

  • OpenResty là gì và nó ăn với cái gì?
  • Tại sao phải phát minh lại bánh xe khi chúng ta có Python, NodeJS, PHP, Go và những thứ hay ho khác mà mọi người đều hài lòng?
  • Và một vài ví dụ thực tế cuộc sống. Mình đã phải cắt report rất nhiều, vì mình lấy trong 3,5 tiếng nên sẽ ít ví dụ.

OpenResty là NGINX. Nhờ anh ấy, chúng tôi có một máy chủ web chính thức, được viết tốt, hoạt động nhanh. Tôi nghĩ rằng hầu hết chúng ta sử dụng NGINX trong sản xuất. Tất cả các bạn đều biết rằng anh ấy nhanh và ngầu. Họ đã tạo ra I / O đồng bộ tuyệt vời trong đó, vì vậy chúng tôi không cần phải quay vòng bất kỳ thứ gì giống như cách mà gevent đã được quay vòng trong Python. Gevent rất hay, rất tuyệt, nhưng nếu bạn viết mã C và có gì đó không ổn với gevent, bạn sẽ phát điên khi gỡ lỗi nó. Tôi đã có kinh nghiệm: phải mất cả hai ngày để tìm ra điều gì đã xảy ra ở đó. Nếu vài tuần trước đó không có ai đó đào bới, tìm ra vấn đề, viết nó lên Internet và Google không tìm ra, thì chúng tôi đã hoàn toàn phát điên.

NGINX đã thực hiện bộ nhớ đệm và nội dung tĩnh. Bạn không cần phải lo lắng về cách thực hiện nó một cách nhân văn, để bạn không bị chậm lại ở đâu đó, để bạn không bị mất các mô tả ở đâu đó. Nginx rất thuận tiện để triển khai, bạn không cần phải suy nghĩ về những gì cần thực hiện - WSGI, PHP-FPM, Gunicorn, Unicorn. Nginx đã được cài đặt, trao cho quản trị viên, họ biết cách làm việc với nó. Nginx xử lý các yêu cầu theo cách có cấu trúc. Tôi sẽ nói về điều này một lát sau. Nói tóm lại, anh ấy có một giai đoạn khi anh ấy vừa chấp nhận yêu cầu, khi anh ấy xử lý và khi anh ấy cung cấp nội dung cho người dùng.

Nginx rất tuyệt, nhưng có một vấn đề: nó không đủ linh hoạt ngay cả với tất cả các tính năng thú vị mà những người này đã đưa vào cấu hình, mặc dù thực tế là nó có thể được tùy chỉnh. Sức mạnh này là không đủ. Do đó, những người từ Taobao ngày xửa ngày xưa, tôi nghĩ khoảng tám năm trước, đã xây dựng Lua vào đó. Anh ấy tặng gì?

  • kích thước. Nó nhỏ. LuaJIT cung cấp khoảng 100-200 kilobyte bộ nhớ và chi phí hoạt động tối thiểu.
  • tốc độ. Trình thông dịch LuaJIT gần với C trong nhiều trường hợp, trong một số trường hợp nó thua Java, trong một số trường hợp nó vượt qua nó. Trong một thời gian, nó được coi là trình biên dịch JIT tuyệt vời nhất, hiện đại nhất. Bây giờ có những cái mát hơn, nhưng chúng rất nặng, chẳng hạn như động cơ V8 giống nhau. Một số trình thông dịch JS và Java HotSpot nhanh hơn ở một số điểm, nhưng vẫn thua ở một số điểm.
  • dễ học. Ví dụ, nếu bạn có một cơ sở mã Perl và bạn không Đăng ký, bạn sẽ không tìm thấy các lập trình viên Perl. Bởi vì họ không có ở đó, tất cả đều bị bắt đi, dạy dỗ họ rất lâu và khó khăn. Nếu bạn muốn lập trình viên cho việc khác, họ cũng có thể phải được đào tạo lại hoặc tìm. Trong trường hợp của Lua, mọi thứ đều đơn giản. Lua có thể được học bởi bất kỳ đàn em nào trong ba ngày. Tôi mất khoảng hai giờ để tìm ra nó. Hai giờ sau, tôi đã viết mã trong quá trình sản xuất. Khoảng một tuần sau, anh ấy đi thẳng vào sản xuất và rời đi.

Kết quả là, nó trông như thế này:

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Có rất nhiều ở đây. OpenResty đã tập hợp một loạt các mô-đun, cả luash và engins. Và bạn đã sẵn sàng mọi thứ - đã triển khai và đang hoạt động.

Ví dụ

Đủ lời bài hát, hãy chuyển sang mã. Đây là một chút Hello World:

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Ở đó có gì vậy? đây là vị trí động cơ. Chúng tôi không lo lắng, chúng tôi không viết định tuyến của riêng mình, chúng tôi không lấy một số định tuyến làm sẵn - chúng tôi đã có nó trong NGINX, chúng tôi sống tốt và lười biếng.

content_by_lua_block là một khối cho biết rằng chúng tôi đang cung cấp nội dung bằng tập lệnh Lua. Chúng tôi lấy một biến động cơ remote_addr và trượt nó vào string.format. Điều này giống như sprintf, chỉ có ở Lúa, mới đúng thôi. Và chúng tôi đưa nó cho khách hàng.

Kết quả là, nó sẽ trông như thế này:

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Nhưng trở lại với thế giới thực. Trong sản xuất, không ai triển khai Hello World. Ứng dụng của chúng tôi thường đi đến cơ sở dữ liệu hoặc một nơi nào khác và hầu hết thời gian nó chờ phản hồi.

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Chỉ cần ngồi và chờ đợi. Không được tốt lắm. Khi 100.000 người dùng đến, chúng tôi rất khó khăn. Do đó, hãy sử dụng một ứng dụng đơn giản làm ví dụ. Chúng tôi sẽ tìm kiếm hình ảnh, ví dụ, con mèo. Chỉ có điều chúng tôi sẽ không chỉ tìm kiếm, chúng tôi sẽ mở rộng các từ khóa và nếu người dùng tìm kiếm "mèo con", chúng tôi sẽ tìm thấy mèo, lông tơ, v.v. Trước tiên, chúng ta cần lấy dữ liệu yêu cầu trên phần phụ trợ. Nó trông như thế này:

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Hai dòng cho phép bạn chọn các tham số GET, không phức tạp. Sau đó, chẳng hạn, chúng tôi lấy thông tin này từ cơ sở dữ liệu có bảng theo từ khóa và phần mở rộng bằng cách sử dụng truy vấn SQL thông thường. Mọi thứ đều đơn giản. Nó trông như thế này:

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Chúng tôi kết nối thư viện resty.mysql, mà chúng tôi đã có sẵn trong bộ. Chúng tôi không cần cài đặt bất cứ thứ gì, mọi thứ đã sẵn sàng. Chỉ định cách kết nối và tạo truy vấn SQL:

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Đó là một chút đáng sợ, nhưng nó hoạt động. Ở đây 10 là giới hạn. Chúng tôi kéo ra 10 bản ghi, chúng tôi lười biếng, chúng tôi không muốn hiển thị nhiều hơn. Trong SQL, tôi quên mất giới hạn.

Sau đó, chúng tôi tìm hình ảnh cho tất cả các truy vấn. Chúng tôi thu thập một loạt các yêu cầu và điền vào bảng Lua có tên reqs, và làm ngx.location.capture_multi.

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Tất cả các yêu cầu này diễn ra song song và câu trả lời được trả lại cho chúng tôi. Thời gian chạy bằng thời gian phản hồi của cái chậm nhất. Nếu tất cả chúng tôi quay lại sau 50 mili giây và chúng tôi đã gửi hàng trăm yêu cầu, thì chúng tôi sẽ nhận được phản hồi sau 50 mili giây.

Vì chúng tôi lười biếng và không muốn viết bộ nhớ đệm và xử lý HTTP, chúng tôi sẽ để NGINX làm mọi thứ cho chúng tôi. Như bạn đã thấy, có một yêu cầu cho url/fetch, anh ta đây rồi:

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Chúng tôi làm cho đơn giản proxy_pass, chỉ định nơi lưu vào bộ đệm, cách thực hiện và mọi thứ đều phù hợp với chúng tôi.

Nhưng điều này là không đủ, chúng tôi vẫn cần cung cấp dữ liệu cho người dùng. Ý tưởng đơn giản nhất là tuần tự hóa mọi thứ thành JSON, một cách dễ dàng, trong hai dòng. Chúng tôi cung cấp Loại nội dung, chúng tôi cung cấp JSON.

Nhưng có một khó khăn: người dùng không muốn đọc JSON. Chúng ta cần thu hút các nhà phát triển front-end. Đôi khi chúng tôi không cảm thấy thích làm điều đó lúc đầu. Vâng, và các chuyên gia SEO sẽ nói rằng nếu chúng ta đang tìm kiếm hình ảnh, thì họ không quan tâm. Và nếu chúng tôi cung cấp cho họ một số nội dung, họ sẽ nói rằng các công cụ tìm kiếm của chúng tôi không lập chỉ mục gì cả.

Làm gì với nó đây? Tất nhiên, chúng tôi sẽ cung cấp cho người dùng HTML. Việc tạo bằng tay cầm không phải là lỗi, vì vậy chúng tôi muốn sử dụng các mẫu. Có một thư viện cho việc này lua-resty-template.

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Bạn hẳn đã nhìn thấy ba chữ cái đáng sợ OPM. OpenResty đi kèm với trình quản lý gói riêng, thông qua đó bạn có thể cài đặt một loạt các mô-đun khác nhau, đặc biệt, lua-resty-template. Đó là một công cụ mẫu đơn giản tương tự như các mẫu Django. Ở đó bạn có thể viết mã và thay thế biến.

Kết quả là, mọi thứ sẽ giống như thế này:

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Chúng tôi đã lấy dữ liệu và hiển thị lại mẫu trong hai dòng. Người dùng hạnh phúc, có mèo. Vì chúng tôi mở rộng yêu cầu, anh ấy cũng nhận được một con dấu lông cho mèo con. Bạn không bao giờ biết, có thể anh ấy đang tìm kiếm nó, nhưng anh ấy không thể hình thành chính xác yêu cầu của mình.

Mọi thứ đều tuyệt vời, nhưng chúng tôi đang trong quá trình phát triển và chúng tôi chưa muốn hiển thị cho người dùng. Hãy làm một ủy quyền. Để làm điều này, hãy xem cách NGINX xử lý yêu cầu về OpenResty:

  • Giai đoạn đầu - truy cập, khi người dùng mới đến và chúng tôi xem xét anh ta theo tiêu đề, theo địa chỉ IP, theo dữ liệu khác. Bạn có thể cắt nó ngay lập tức nếu chúng tôi không thích nó. Điều này có thể được sử dụng để ủy quyền hoặc nếu chúng tôi nhận được nhiều yêu cầu, chúng tôi có thể dễ dàng cắt chúng ở giai đoạn này.
  • viết lại. Viết lại một số dữ liệu yêu cầu.
  • nội dung. Chúng tôi cung cấp nội dung cho người dùng.
  • bộ lọc tiêu đề. Thay đổi tiêu đề phản hồi. Nếu chúng ta sử dụng proxy_pass, chúng ta có thể viết lại một số tiêu đề trước khi cung cấp cho người dùng.
  • bộ lọc cơ thể. Chúng ta có thể thay đổi cơ thể.
  • đăng nhập - khai thác gỗ. Có thể ghi nhật ký trong elaticsearch mà không cần lớp bổ sung.

Ủy quyền của chúng tôi sẽ giống như thế này:

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Chúng tôi sẽ thêm nó vào đó location, mà chúng tôi đã mô tả trước đây và đặt đoạn mã sau vào đó:

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Chúng tôi xem liệu chúng tôi có mã thông báo cookie hay không. Nếu không, thì chúng tôi sẽ ủy quyền. Người dùng tinh ranh và có thể đoán rằng mã thông báo cookie cần được đặt. Do đó, chúng tôi cũng sẽ đặt nó trong Redis:

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Mã để làm việc với Redis rất đơn giản và không khác gì các ngôn ngữ khác. Đồng thời, tất cả các đầu vào / đầu ra, cái gì ở đó, cái gì ở đây, nó không bị chặn. Nếu bạn viết mã đồng bộ, thì nó hoạt động không đồng bộ. Giống như với gevent, chỉ được thực hiện tốt.

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Hãy tự mình ủy quyền:

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Chúng tôi nói rằng chúng tôi cần đọc phần thân yêu cầu. Chúng tôi nhận được các đối số POST, kiểm tra xem thông tin đăng nhập và mật khẩu có chính xác không. Nếu không chính xác, thì chúng tôi sẽ ủy quyền. Và nếu chúng đúng, thì chúng tôi viết mã thông báo cho Redis:

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Đừng quên đặt cookie, điều này cũng được thực hiện theo hai dòng:

OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Ví dụ rất đơn giản, mang tính suy đoán. Tất nhiên, chúng tôi sẽ không tạo ra một dịch vụ cho mọi người xem mèo. Nhưng ai biết chúng ta. Vì vậy, hãy xem xét những gì có thể được thực hiện trong sản xuất.

  • phụ trợ tối giản. Đôi khi chúng ta cần cung cấp khá nhiều dữ liệu cho phần phụ trợ: ở đâu đó chúng ta cần thay thế ngày, ở đâu đó chúng ta cần hiển thị một loại danh sách nào đó, chẳng hạn như hiện có bao nhiêu người dùng trên trang web, vặn vào bộ đếm hoặc số liệu thống kê. Một cái gì đó rất nhỏ. Một số mảnh tối thiểu có thể được thực hiện rất dễ dàng. Điều này sẽ nhanh chóng, dễ dàng và tuyệt vời.
  • tiền xử lý dữ liệu. Đôi khi, chúng tôi muốn nhúng quảng cáo vào trang của mình và chúng tôi nhận những quảng cáo này bằng các yêu cầu API. Điều này là rất dễ dàng để làm ở đây. Chúng tôi không tải phần phụ trợ của mình, phần phụ trợ đang hoạt động tích cực. Bạn có thể nhặt và sưu tầm tại đây. Chúng ta có thể nhào nặn một số JS hoặc ngược lại, bỏ dính, xử lý trước một cái gì đó trước khi đưa nó cho người dùng.
  • Mặt tiền cho microservice. Đây cũng là một trường hợp rất hay, tôi đã thực hiện nó. Trước đó, tôi đã làm việc cho Tenzor, một công ty báo cáo điện tử cung cấp báo cáo cho khoảng một nửa số pháp nhân trong nước. Chúng tôi đã tạo một dịch vụ, nhiều thứ được thực hiện ở đó bằng cách sử dụng cùng một cơ chế: định tuyến, ủy quyền, v.v.
    OpenResty có thể được sử dụng làm chất kết dính cho các dịch vụ siêu nhỏ của bạn để cung cấp một quyền truy cập duy nhất vào mọi thứ và một giao diện duy nhất. Vì các dịch vụ siêu nhỏ có thể được viết theo cách mà bạn có Node.js ở đây, bạn có PHP ở đây, bạn có Python ở đây, có một số thứ Erlang ở đây, chúng tôi hiểu rằng chúng tôi không muốn viết lại cùng một mã ở mọi nơi. Do đó, OpenResty có thể được cắm vào phía trước.

  • Thống kê và phân tích. Thông thường NGINX ở lối vào và tất cả các yêu cầu đều đi qua nó. Đó là ở nơi này, nó rất thuận tiện để thu thập. Bạn có thể ngay lập tức tính toán một thứ gì đó và ném nó đi đâu đó, chẳng hạn như cùng một Elaticsearch, Logstash hoặc chỉ cần ghi nó vào nhật ký rồi gửi nó đi đâu đó.
  • Hệ thống nhiều người dùng. Ví dụ, trò chơi trực tuyến cũng rất tốt để làm. Hôm nay tại Cape Town, Alexander Gladysh sẽ cho bạn biết cách nhanh chóng thử nghiệm một trò chơi nhiều người chơi bằng OpenResty.
  • Lọc yêu cầu (WAF). Hiện nay, việc tạo tất cả các loại tường lửa cho ứng dụng web đang là mốt, có rất nhiều dịch vụ cung cấp chúng. Với sự trợ giúp của OpenResty, bạn có thể tạo cho mình một tường lửa ứng dụng web, ứng dụng này sẽ lọc các yêu cầu theo yêu cầu của bạn một cách đơn giản và dễ dàng. Nếu bạn có Python, thì bạn hiểu rằng PHP chắc chắn sẽ không được đưa vào cho bạn, tất nhiên, trừ khi bạn tạo ra nó ở bất kỳ đâu từ bảng điều khiển. Bạn biết bạn có MySQL và Python. Có lẽ, ở đây họ có thể cố gắng thực hiện một số loại duyệt thư mục và đưa thứ gì đó vào cơ sở dữ liệu. Do đó, bạn có thể lọc ra các yêu cầu ngớ ngẩn một cách nhanh chóng và rẻ tiền ngay từ đầu.
  • Cộng đồng. Vì OpenResty dựa trên NGINX nên nó có một phần thưởng - đây là cộng đồng NGINX. Nó rất lớn và rất nhiều câu hỏi ban đầu bạn sẽ có đã được cộng đồng NGINX trả lời.

    nhà phát triển Lua. Hôm qua mình có nói chuyện với các bác đến buổi training HighLoad++ nghe nói chỉ có Tarantool viết bằng Lua. Điều này không phải vậy, rất nhiều thứ được viết bằng Lua. Ví dụ: OpenResty, máy chủ Prosody XMPP, công cụ trò chơi Love2D, Lua được viết kịch bản trong Warcraft và các nơi khác. Có rất nhiều nhà phát triển Lua, họ có một cộng đồng lớn và nhanh nhạy. Tất cả các câu hỏi về Lua của tôi đã được trả lời trong vòng vài giờ. Khi bạn viết thư cho danh sách gửi thư, nghĩa đen là trong vài phút đã có rất nhiều câu trả lời, chúng mô tả cái gì và như thế nào, cái gì. Thật tuyệt vời. Thật không may, một cộng đồng chân thành như vậy không phải ở đâu cũng có.
    OpenResty có GitHub, nơi bạn có thể mở một vấn đề nếu có lỗi xảy ra. Có một danh sách gửi thư trên Google Groups nơi bạn có thể thảo luận các vấn đề chung, có một danh sách gửi thư bằng tiếng Trung - bạn không bao giờ biết, có thể bạn không nói được tiếng Anh, nhưng bạn có kiến ​​thức về tiếng Trung.

Kết quả

  • Tôi hy vọng tôi có thể truyền đạt rằng OpenResty là một khuôn khổ web rất thuận tiện.
  • Nó có ngưỡng đầu vào thấp, vì mã tương tự như những gì chúng tôi viết, ngôn ngữ khá đơn giản và tối giản.
  • Nó cung cấp I/O không đồng bộ mà không cần gọi lại, chúng tôi sẽ không có mì như đôi khi chúng tôi có thể viết bằng NodeJS.
  • Nó có một triển khai dễ dàng, bởi vì chúng tôi chỉ cần NGINX với mô-đun phù hợp và mã của chúng tôi, và mọi thứ sẽ hoạt động ngay lập tức.
  • Cộng đồng lớn và đáp ứng.

Tôi không kể chi tiết việc định tuyến được thực hiện như thế nào, hóa ra đó là một câu chuyện rất dài.

Cảm ơn bạn!


Vladimir Protasov - OpenResty: biến NGINX thành một máy chủ ứng dụng chính thức

Nguồn: www.habr.com

Thêm một lời nhận xét