Làm thế nào để kiến ​​trúc hệ thống microservice tránh tắc nghẽn mạng?


72

Tôi đã đọc rất nhiều về kiến ​​trúc microservice cho các ứng dụng máy chủ và đã tự hỏi làm thế nào việc sử dụng mạng nội bộ không phải là một nút cổ chai hoặc một bất lợi đáng kể so với kiến ​​trúc nguyên khối.

Vì mục đích chính xác, đây là những diễn giải của tôi về hai thuật ngữ:

  1. Kiến trúc nguyên khối: Một ứng dụng trong một ngôn ngữ duy nhất xử lý tất cả các chức năng, dữ liệu, v.v ... Bộ cân bằng tải phân phối các yêu cầu từ người dùng cuối trên nhiều máy, mỗi ứng dụng chạy một phiên bản của ứng dụng của chúng tôi.

  2. Kiến trúc microservice : Nhiều ứng dụng (microservice) xử lý một phần nhỏ chức năng và dữ liệu. Mỗi microservice hiển thị một API chung được truy cập qua mạng (trái ngược với giao tiếp giữa các quá trình hoặc bộ nhớ dùng chung trên cùng một máy). Các lệnh gọi API được đặt chủ yếu trên máy chủ để tạo một trang, mặc dù có lẽ một số công việc này được thực hiện bởi máy khách truy vấn các dịch vụ micros micros riêng lẻ.

Theo trí tưởng tượng ngây thơ của tôi, có vẻ như kiến ​​trúc microservice sử dụng lưu lượng mạng chậm thay vì tài nguyên nhanh hơn trên cùng một máy (bộ nhớ và đĩa). Làm cách nào để đảm bảo rằng truy vấn API qua mạng nội bộ sẽ không làm chậm thời gian phản hồi chung?


Mạng nội bộ thường là 1 Gbps, đôi khi nhanh hơn. Hãy suy nghĩ về kích thước trung bình của phản hồi JSON từ API. Có bao nhiêu phản hồi như vậy có thể được truyền qua kết nối 1 Gbps trong một giây?
Arseni Mourzenko

3
nếu bạn nghĩ rằng bạn cần microservice - và bạn có thể! - hai cuốn sách tuyệt vời để chuẩn bị: amazon.com/Building-Microservices-Sam-Newman/dp/1491950358amazon.com/Release-It-Production-Ready-Pragmatic-Programmers/dp/...
Steven A. Lowe

@MainMa vấn đề không nằm ở băng thông, mà là sự chậm trễ. Và nếu bạn cần làm tròn số, bạn sẽ ngạc nhiên về mức độ băng thông thực tế bạn có thể sử dụng
Stephan Eggermont

Câu trả lời:


61

Mạng nội bộ thường sử dụng kết nối 1 Gbps hoặc nhanh hơn. Kết nối hoặc liên kết sợi quang cho phép băng thông cao hơn nhiều giữa các máy chủ. Bây giờ hãy tưởng tượng kích thước trung bình của phản hồi JSON từ API. Bao nhiêu phản hồi như vậy có thể được truyền qua kết nối 1 Gbps trong một giây?

Hãy thực sự làm toán. 1 Gbps là 131 072 KB mỗi giây. Nếu một phản hồi JSON trung bình là 5 KB (khá nhiều!), Bạn có thể gửi 26 214 phản hồi mỗi giây thông qua dây chỉ với một cặp máy . Không tệ lắm phải không?

Đây là lý do tại sao kết nối mạng thường không phải là nút cổ chai.

Một khía cạnh khác của microservice là bạn có thể mở rộng quy mô dễ dàng. Hãy tưởng tượng hai máy chủ, một máy chủ lưu trữ API, một máy chủ khác tiêu thụ nó. Nếu bao giờ kết nối trở thành nút cổ chai, chỉ cần thêm hai máy chủ khác và bạn có thể tăng gấp đôi hiệu suất.

Đây là khi 26 214 phản hồi trước đó của chúng tôi trở nên quá nhỏ so với quy mô của ứng dụng. Bạn thêm chín cặp khác và hiện bạn có thể phục vụ 262 140 phản hồi.

Nhưng hãy quay trở lại cặp máy chủ của chúng tôi và làm một số so sánh.

  • Nếu một truy vấn không lưu trong bộ nhớ cache trung bình vào cơ sở dữ liệu mất 10 ms, thì bạn bị giới hạn ở 100 truy vấn mỗi giây. 100 truy vấn. 26 214 phản hồi. Để đạt được tốc độ 26 214 phản hồi mỗi giây đòi hỏi một lượng lớn bộ nhớ đệm và tối ưu hóa (nếu phản hồi thực sự cần phải làm điều gì đó hữu ích, như truy vấn cơ sở dữ liệu; phản hồi kiểu "Hello World" không đủ điều kiện).

  • Trên máy tính của tôi, ngay bây giờ, DOMContentLoaded cho trang chủ của Google đã xảy ra 394 ms. sau khi yêu cầu được gửi đi Đó là ít hơn 3 yêu cầu mỗi giây. Đối với trang chủ Lập trình viên. Nó đã xảy ra 603 ms. sau khi yêu cầu được gửi đi Đó thậm chí không phải là 2 yêu cầu mỗi giây. Nhân tiện, tôi có kết nối internet 100 Mbps và máy tính nhanh: nhiều người dùng sẽ đợi lâu hơn.

    Nếu nút cổ chai là tốc độ mạng giữa các máy chủ, hai trang web đó thực sự có thể thực hiện hàng ngàn cuộc gọi đến các API khác nhau trong khi phục vụ trang.

Hai trường hợp đó cho thấy rằng mạng có thể sẽ không phải là nút cổ chai của bạn trên lý thuyết (trong thực tế, bạn nên thực hiện các điểm chuẩn thực tế và định hình để xác định vị trí chính xác của nút cổ chai của hệ thống cụ thể của bạn được lưu trữ trên một phần cứng cụ thể). Thời gian dành cho công việc thực tế (sẽ là các truy vấn SQL, nén, bất cứ điều gì) và gửi kết quả cho người dùng cuối quan trọng hơn nhiều.

Nghĩ về cơ sở dữ liệu

Thông thường, cơ sở dữ liệu được lưu trữ riêng biệt với ứng dụng web sử dụng chúng. Điều này có thể gây lo ngại: tốc độ kết nối giữa máy chủ lưu trữ ứng dụng và máy chủ lưu trữ cơ sở dữ liệu thì sao?

Dường như có những trường hợp thực sự, tốc độ kết nối trở nên có vấn đề, đó là khi bạn lưu trữ một lượng dữ liệu khổng lồ không cần xử lý bởi chính cơ sở dữ liệu và nên có sẵn ngay bây giờ (đó là các tệp nhị phân lớn). Nhưng những tình huống như vậy rất hiếm: trong hầu hết các trường hợp, tốc độ truyền không lớn so với tốc độ xử lý truy vấn của chính nó.

Khi tốc độ truyền thực sự có vấn đề là khi một công ty lưu trữ các tập dữ liệu lớn trên NAS và NAS được nhiều khách hàng truy cập cùng một lúc. Đây là nơi SAN có thể là một giải pháp. Điều này đang được nói, đây không phải là giải pháp duy nhất. Cáp Cat 6 có thể hỗ trợ tốc độ lên tới 10 Gbps; liên kết cũng có thể được sử dụng để tăng tốc độ mà không thay đổi cáp hoặc bộ điều hợp mạng. Các giải pháp khác tồn tại, liên quan đến sao chép dữ liệu trên nhiều NAS.

Hãy quên đi tốc độ; nghĩ về khả năng mở rộng

Một điểm quan trọng của một ứng dụng web là có thể mở rộng quy mô. Mặc dù hiệu suất thực tế quan trọng (vì không ai muốn trả tiền cho các máy chủ mạnh hơn), khả năng mở rộng quan trọng hơn nhiều, vì nó cho phép bạn ném thêm phần cứng khi cần.

  • Nếu bạn có một ứng dụng không đặc biệt nhanh, bạn sẽ mất tiền vì bạn sẽ cần các máy chủ mạnh hơn.

  • Nếu bạn có một ứng dụng nhanh không thể mở rộng quy mô, bạn sẽ mất khách hàng vì bạn sẽ không thể đáp ứng nhu cầu ngày càng tăng.

Theo cùng một cách, các máy ảo cách đây một thập kỷ được coi là một vấn đề hiệu năng rất lớn. Thật vậy, lưu trữ một ứng dụng trên máy chủ so với lưu trữ trên máy ảo có tác động hiệu suất quan trọng. Trong khi khoảng cách ngày nay nhỏ hơn nhiều, nó vẫn tồn tại.

Mặc dù mất hiệu năng này, môi trường ảo đã trở nên rất phổ biến vì tính linh hoạt mà chúng mang lại.

Cũng như tốc độ mạng, bạn có thể thấy VM là nút cổ chai thực tế và với quy mô thực tế của bạn, bạn sẽ tiết kiệm hàng tỷ đô la bằng cách lưu trữ ứng dụng của mình trực tiếp mà không cần VM. Nhưng đây không phải là điều xảy ra đối với 99,9% ứng dụng: nút cổ chai của chúng ở một nơi khác và nhược điểm của việc mất vài micro giây vì VM dễ dàng được bù đắp bởi lợi ích của khả năng trừu tượng hóa và khả năng mở rộng.


Chắc chắn, chúng ta có thể nói rằng các phản hồi JSON là nhỏ, nhưng số lượng của chúng thì sao? Tôi cảm thấy như một trang web chịu tải nặng sẽ có lưu lượng mạng nhiều hơn trong kiến ​​trúc microservice so với kiến ​​trúc nguyên khối (trong đó lưu lượng mạng duy nhất đến / từ (các) máy chủ cơ sở dữ liệu). Bộ nhớ đệm có thể giúp ích, nhưng đối với thời gian thực và / hoặc nội dung được tạo động, tôi không biết bộ nhớ đệm sẽ đi được bao xa.
James Mishra

@JamesMishra: Tôi đã chỉnh sửa câu trả lời của mình để giải quyết những lo lắng của bạn.
Arseni Mourzenko 10/03/2015

Câu trả lời của bạn là hoàn hảo . Bạn không chỉ trả lời mọi phản đối mà tôi có thể nghĩ ra, mà bạn còn trả lời những phản đối mà tôi không nghĩ tới.
James Mishra

5
2 Cents của tôi từ thế giới thực: Một hệ thống bao gồm các dịch vụ siêu nhỏ rất trò chuyện có thể chịu các vấn đề về hiệu suất hoàn toàn do mạng bị nghẹt thở. Bộ nhớ đệm và thiết kế dựa trên Luồng sự kiện là bạn của bạn trong những trường hợp như vậy. Bên cạnh mạng, CPU và bộ nhớ, một hệ thống dựa trên microservice cũng cần kết hợp khả năng phục hồi trong thiết kế của nó: điều gì xảy ra nếu microservice ngừng hoạt động? Làm thế nào để bạn xây dựng thử lại, giao dịch phân tán, tự phục hồi, theo dõi - Tôi khuyên bạn nên tìm kiếm "bạn phải cao như vậy để sử dụng microservice"
Sudhanshu Mishra

4
Vui lòng sửa lại cho tôi nếu tôi sai, nhưng theo tôi biết, nếu bạn có mạng 1Gbps, điều đó có nghĩa là về mặt lý thuyết bạn có thể gửi dữ liệu trị giá 1Gb mỗi giây qua mạng đó. Bất kể số lượng kết nối. Số lượng kết nối càng cao, băng thông cho mỗi kết nối càng thấp. Vì vậy, giới hạn thực tế của bạn mà không nâng cấp mạng của bạn để hỗ trợ băng thông cao hơn sẽ là 26.214 phản hồi mỗi giây. Thêm nhiều máy chủ sẽ không làm tăng băng thông mạng của bạn. Nếu một cụm duy nhất có thể tạo ra lưu lượng truy cập đó, việc thêm nhiều máy chủ tạo ra nhiều dữ liệu hơn sẽ làm tắc nghẽn mạng của bạn.
Sebbe

7

Tôi nghĩ rằng bạn đang đọc quá nhiều vào phần 'vi mô'. Điều đó không có nghĩa là thay thế mọi lớp bằng một dịch vụ mạng, nhưng cấu thành một ứng dụng nguyên khối thành các thành phần có kích thước hợp lý, mỗi lớp xử lý một khía cạnh của chương trình của bạn. Các dịch vụ sẽ không nói chuyện với nhau, vì vậy, tệ nhất là bạn đã chia một yêu cầu mạng lớn thành nhiều yêu cầu nhỏ hơn. Dữ liệu được trả về sẽ không khác biệt đáng kể so với những gì bạn nhận được (mặc dù bạn có thể trả lại nhiều dữ liệu hơn và hợp nhất dữ liệu đó trong máy khách)


3
"Các dịch vụ sẽ không nói chuyện với nhau." Tôi tưởng tượng rằng microservice có thể có các phụ thuộc được chia sẻ (xác thực, có lẽ?) Mà người ta có thể tách thành một dịch vụ siêu nhỏ khác. LDAP, theo một nghĩa nào đó, là một dịch vụ siêu nhỏ xác thực và tôi tưởng tượng rằng tất cả các dịch vụ siêu nhỏ khác đều nói chuyện với nó. Hay ... xác thực chỉ xảy ra một lần? Làm thế nào để mỗi microservice kiểm tra quyền đối với xác thực để ngăn chặn các cuộc tấn công Truy cập đối tượng trực tiếp?
James Mishra

2
@JamesMishra tốt .. nó phụ thuộc. Khi tôi sử dụng kiến ​​trúc microservice lần cuối, mỗi dịch vụ hoàn toàn độc lập với các dịch vụ khác vì mục đích bảo mật (nhưng cũng là lý do silo của công ty). Auth được xử lý bởi mỗi khác nhau, mặc dù được kiểm soát bởi chính sách kiến ​​trúc. Tuy nhiên, chẳng có lý do gì họ không thể nói chuyện với auth chẳng hạn, hoặc chỉ có auth dựa trên thư viện. Nhưng .. tôi đã cố gắng nói rằng họ không nên thực hiện nhiều cuộc gọi giữa họ, không phải họ không nên sử dụng dịch vụ như chính khách hàng.
gbjbaanb

@JamesMishra, auth thường là dịch vụ riêng trong các môi trường này và vì vậy mỗi dịch vụ chỉ nên sử dụng dịch vụ đó thay vì tự thực hiện đầy đủ.
Paul

2

Bằng cách cấu trúc mã và truy cập tài nguyên của bạn sao cho hệ thống kết quả có thể đủ linh hoạt để chạy như một ứng dụng nguyên khối hoặc phân phối thông qua cấu hình. Nếu bạn trừu tượng hóa cơ chế giao tiếp đằng sau một số giao diện phổ biến và bạn xây dựng hệ thống của mình một cách đồng thời, bạn có thể dễ dàng tối ưu hóa mọi thứ sau khi bạn đã cấu hình hệ thống của mình và tìm thấy cổ chai thực sự.


Một ví dụ để giải thích những gì tôi cho rằng @mortalapeman có nghĩa là: bạn có giao diện java / c # IP sinhtAvailibitiy trong đó tất cả người tiêu dùng IP sinhtAvailibitiy được liên kết với. Ngoài ra còn có một lớp ProductAvailibitiyImpl thực hiện giao diện này và một ProductAvailibitiyMicroservice sử dụng ProductAvailibitiyImpl. Người tiêu dùng có thể được định cấu hình để sử dụng ProductAvailibitiyImpl cục bộ hoặc proxy từ xa tới ProductAvailibitiyMicroservice
k3b

2

Tôi muốn thêm một góc nhìn khác, từ một ngành khác với các giả định rất khác nhau - mô phỏng (cấp thực thể). Về mặt khái niệm, đây rất giống với một trò chơi video FPS phân tán. Sự khác biệt chính: tất cả người chơi chia sẻ một số trạng thái: nơi con rồng đang ở ngay bây giờ; không có cuộc gọi cơ sở dữ liệu; mọi thứ đều được giữ trong RAM vì tốc độ và độ trễ thấp, thông lượng ít liên quan hơn (nhưng tôi đoán bạn cũng không thể bỏ qua hoàn toàn).

Bạn có thể nghĩ mỗi ứng dụng tham gia là một khối nguyên khối (đại diện cho tất cả các khía cạnh của người chơi) hoặc dưới dạng microservice (chỉ đại diện cho một người chơi trong đám đông).

Các đồng nghiệp của tôi đã quan tâm đến việc phá vỡ một ứng dụng tham gia duy nhất, hơn nữa là các dịch vụ siêu nhỏ có thể được chia sẻ, ví dụ như phân xử thiệt hại hoặc tính toán tầm nhìn, những thứ thường được đưa vào mô phỏng.

Vấn đề là độ trễ của việc gửi các cuộc gọi và chờ đợi yêu cầu. Băng thông là không liên quan và phong phú dù sao, như những người khác đã chỉ ra. Nhưng nếu tính toán tầm nhìn đi từ 1 microsec đến 100 microsec (giả sử, do xếp hàng trong microservice mới được chia sẻ giữa tất cả các ứng dụng của người chơi), đó là một mất mát lớn (có thể cần một vài hoặc nhiều tính toán tầm nhìn cho mỗi bản cập nhật, một vài cập nhật / giây).

Hãy suy nghĩ thật kỹ về cách các dịch vụ hoạt động, khi chúng được gọi và dữ liệu nào được trao đổi. Các ứng dụng của chúng tôi đã không trao đổi thông tin vị trí, chúng trao đổi thông tin tính toán chết - Tôi đang ở vị trí x, đi theo hướng y ở tốc độ q. Và tôi không phải cập nhật thông tin của mình cho đến khi những giả định đó thay đổi. Nhiều cập nhật ít hơn và độ trễ (trong khi vẫn còn một vấn đề) xuất hiện theo tỷ lệ ít thường xuyên hơn.

Vì vậy, thay vì yêu cầu dịch vụ ở mức hạt mịn với tần suất cao hơn, hãy thử giảm tần suất bằng cách:

  1. thay đổi dữ liệu nào được yêu cầu và sử dụng tính toán cục bộ
  2. gửi tham số kích hoạt hoặc truy vấn cho phản hồi không đồng bộ
  3. yêu cầu theo đợt
  4. dự đoán các yêu cầu và chuẩn bị phản hồi trước, về đầu cơ (ngược lại với đánh giá lười biếng)
  5. bất cứ khi nào có thể, tránh microservice gọi microservice khác; Điều này hợp chất vấn đề, rõ ràng. Tôi hiểu rằng đây là một sự khích lệ để làm cho các dịch vụ siêu nhỏ trở nên lớn hơn và phần nào đánh bại điểm này, nhưng các dịch vụ siêu nhỏ không phải là bạn của độ trễ. Có lẽ chỉ cần thừa nhận nó và vượt qua nó.

Bây giờ hãy nhớ kiểm tra các giả định của bạn về hệ thống của bạn. Nếu bạn quan tâm đến thông lượng hơn độ trễ hoặc không có trạng thái chia sẻ, v.v., thì bằng mọi cách, hãy sử dụng microservice khi chúng có ý nghĩa. Tôi chỉ nói có thể không sử dụng chúng khi chúng không có ý nghĩa.


1

Trí tưởng tượng ngây thơ của bạn là đúng. Và thường thì điều đó không thành vấn đề. Máy móc hiện đại nhanh. Những lợi thế chính của kiến ​​trúc dịch vụ vi mô được nhìn thấy trong nỗ lực và thời gian phát triển và bảo trì.

Và tất nhiên, không có quy tắc nào nói rằng bạn không thể sử dụng bộ nhớ dùng chung hoặc thậm chí triển khai vật lý nhiều dịch vụ trong một lần thực thi. Chỉ cần bạn thiết kế nó không bị phụ thuộc vào điều đó.


CPU rất nhanh. Bộ nhớ nhanh. SSD rất nhanh. Nhưng các card mạng và bộ định tuyến và chuyển mạch "nhanh"? Một câu trả lời khác khẳng định như vậy, nhưng tôi không chắc chắn.
James Mishra

Nó chắc chắn là dễ dàng để chạy vào các vấn đề tốc độ mạng. Điều hành một dịch vụ ở San Francisco, một dịch vụ khác ở Amsterdam và tiêu thụ chúng ở Sydney. Độ trễ là chìa khóa, không phải băng thông. Vì vậy, đừng làm điều đó. Và làm cho các dịch vụ lớn như có ý nghĩa
Stephan Eggermont

1

Như nhiều người đã đề cập, nó không phải là về các nút thắt mạng. Đó là nhiều hơn về độ giòn của mạng. Vì vậy, bước đầu tiên là tránh giao tiếp đồng bộ. Nó dễ hơn âm thanh. Tất cả bạn cần là dịch vụ với ranh giới đúng. Ranh giới bên phải dẫn đến các dịch vụ được tự chủ, liên kết lỏng lẻo và có tính gắn kết cao. Dịch vụ tốt không cần thông tin từ dịch vụ khác, nó đã có sẵn. Cách duy nhất để dịch vụ tốt giao tiếp là thông qua các sự kiện. Các dịch vụ tốt cuối cùng cũng phù hợp, do đó không có giao dịch phân tán.

Cách để đạt được sự tốt đẹp này là xác định khả năng kinh doanh của bạn trước tiên. Năng lực kinh doanh là một trách nhiệm kinh doanh cụ thể. Một số đóng góp cho giá trị kinh doanh tổng thể. Vì vậy, đây là trình tự bước của tôi mà tôi thực hiện khi nghĩ về ranh giới hệ thống:

  1. Xác định trách nhiệm kinh doanh cấp cao hơn. Sẽ có một vài trong số họ. Hãy coi dịch vụ này là một bước mà tổ chức của bạn nên thực hiện để đạt được mục tiêu kinh doanh của mình.
  2. Tìm hiểu sâu hơn trong từng dịch vụ. Xác định các dịch vụ cấp thấp hơn bao gồm một phụ huynh.
  3. Bên cạnh hai điểm đầu tiên nghĩ về giao tiếp dịch vụ. Họ nên làm điều đó chủ yếu thông qua các sự kiện, chỉ để thông báo cho nhau về kết quả quá trình kinh doanh của họ. Sự kiện không nên được coi là băng tải dữ liệu.

Hãy nhớ rằng dịch vụ kinh doanh bao gồm con người, ứng dụng, quy trình kinh doanh. Thông thường chỉ một phần của nó được đại diện như cơ quan kỹ thuật.

Điều này nghe có vẻ hơi trừu tượng, vì vậy có lẽ một ví dụ về nhận dạng ranh giới dịch vụ sẽ được quan tâm.


0

Chỉ cần một yếu tố khác để thêm vào các câu trả lời hiện tại. Với một dịch vụ hạt thô . Bạn muốn tránh độ trễ từ tất cả các cuộc gọi, vì vậy thay vì thực hiện 10 cuộc gọi, bạn thực hiện một cuộc gọi nhận được 10 mẩu dữ liệu cần thiết trong DTO.

Và hãy nhớ rằng microservice không vi mô như mọi người nghĩ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.