Điều gì xảy ra nếu tôi bắt đầu quá nhiều công việc nền?


13

Tôi cần thực hiện một số công việc trên 700 thiết bị mạng bằng cách sử dụng tập lệnh mong đợi. Tôi có thể hoàn thành nó một cách tuần tự, nhưng cho đến nay thời gian chạy là khoảng 24 giờ. Điều này chủ yếu là do thời gian cần thiết để thiết lập kết nối và sự chậm trễ trong đầu ra từ các thiết bị này (thiết bị cũ). Tôi có thể thiết lập hai kết nối và để chúng chạy song song tốt, nhưng tôi có thể đẩy nó bao xa?

Tôi không tưởng tượng rằng tôi có thể làm tất cả 700 người trong số họ cùng một lúc, chắc chắn có giới hạn nào đó là không. kết nối telnet VM của tôi có thể quản lý.

Nếu tôi đã cố gắng bắt đầu 700 trong số chúng trong một số vòng lặp như thế này:

for node in `ls ~/sagLogs/`; do  
    foo &  
done

Với

  • CPU 12 CPU x Intel (R) Xeon (R) CPU E5649 @ 2.53GHz

  • Bộ nhớ 47,94 GB

Câu hỏi của tôi là:

  1. Tất cả 700 trường hợp có thể chạy đồng thời?
  2. Tôi có thể đi bao xa cho đến khi máy chủ của tôi đạt đến giới hạn?
  3. Khi đạt đến giới hạn đó, nó sẽ đợi để bắt đầu lần lặp tiếp theo tắt foohay hộp sẽ sụp đổ?

Thật không may, tôi đang chạy trong một môi trường sản xuất của công ty, vì vậy tôi không thể chính xác thử xem điều gì sẽ xảy ra.


3
Tôi đã có may mắn với parallel, sử dụng khoảng 50 công việc đồng thời. Đó là một phương tiện tuyệt vời giữa song song 1 và 700. Một điều tuyệt vời khác là không có lô. Một kết nối bị đình trệ duy nhất sẽ chỉ bị đình trệ, không phải bất kỳ kết nối nào khác. Nhược điểm chính là quản lý lỗi. Không có cách tiếp cận dựa trên vỏ nào sẽ xử lý lỗi một cách duyên dáng. Bạn sẽ phải tự kiểm tra thành công và tự mình thử lại.
Adam

1
Hàng đợi nhiệm vụ của bạn có thể là 700 ngày hôm nay, nhưng kích thước có thể mở rộng? Theo dõi không gian hoán đổi để phát triển - đó là dấu hiệu bạn đã đạt đến giới hạn bộ nhớ. Và cpu% không phải là một biện pháp tốt (đối với linux / unix), tốt hơn để xem xét mức trung bình tải (chạy chiều dài hàng đợi).
ChuckCottrill

1
Cách gần đây nhất tôi đã phá vỡ sản xuất trong công việc vẫn còn mới của mình là vô tình điều hành một triệu công việc nền tảng ngắn ngủi cùng một lúc. Họ liên quan đến các JVM (chờ đợi đặt các cú ném xuống), do đó, hậu quả là 'giới hạn' đối với hàng trăm ngàn tệp báo cáo lỗi mà các luồng không thể bắt đầu.
michaelb958 - GoFundMonica


1
@KuboMD Và miễn là không ai khác muốn sử dụng mã của bạn.
l0b0

Câu trả lời:


17

Tất cả 700 trường hợp có thể chạy đồng thời?

Điều đó phụ thuộc vào những gì bạn có nghĩa là đồng thời. Nếu chúng ta kén chọn, thì không, họ không thể trừ khi bạn có 700 luồng thực thi trên hệ thống của mình, bạn có thể sử dụng (có lẽ là không). Trên thực tế, vâng, có lẽ họ có thể, miễn là bạn có đủ RAM và / hoặc trao đổi không gian trên hệ thống. UNIX và nhiều trẻ em khác nhau rất giỏi trong việc quản lý mức độ đồng thời rất lớn, đó là một phần lý do tại sao chúng rất phổ biến để sử dụng HPC quy mô lớn.

Tôi có thể đi bao xa cho đến khi máy chủ của tôi đạt đến giới hạn?

Điều này là không thể trả lời cụ thể mà không có nhiều thông tin hơn. Khá nhiều, bạn cần có đủ bộ nhớ để đáp ứng:

  • Toàn bộ yêu cầu bộ nhớ thời gian chạy của một công việc, gấp 700 lần.
  • Các yêu cầu về bộ nhớ của bash để quản lý nhiều công việc đó (bash không kinh khủng về điều này, nhưng kiểm soát công việc không chính xác là hiệu quả bộ nhớ).
  • Bất kỳ yêu cầu bộ nhớ khác trên hệ thống.

Giả sử bạn đáp ứng điều đó (một lần nữa, chỉ với 50GB RAM, bạn vẫn chưa giải quyết được các vấn đề khác:

  • Bao nhiêu thời gian CPU sẽ bị lãng phí bởi bash về kiểm soát công việc? Có lẽ không nhiều, nhưng với hàng trăm công việc, nó có thể là đáng kể.
  • Cần bao nhiêu băng thông mạng? Chỉ cần mở tất cả các kết nối đó có thể tràn ngập mạng của bạn trong vài phút tùy thuộc vào băng thông và độ trễ của bạn.
  • Nhiều thứ khác có lẽ tôi chưa từng nghĩ tới.

Khi đạt đến giới hạn đó, nó sẽ đợi để bắt đầu lần lặp tiếp theo tắt foo hay hộp sẽ sụp đổ?

Nó phụ thuộc vào giới hạn nào được đạt. Nếu là bộ nhớ, một cái gì đó sẽ chết trên hệ thống (cụ thể hơn là bị kernel giết chết trong nỗ lực giải phóng bộ nhớ) hoặc chính hệ thống có thể gặp sự cố (không có gì bất thường khi cấu hình các hệ thống cố tình gặp sự cố khi hết bộ nhớ). Nếu đó là thời gian CPU, nó sẽ tiếp tục hoạt động mà không gặp vấn đề gì, sẽ không thể làm gì khác trên hệ thống. Nếu đó là mạng, bạn có thể gặp sự cố với các hệ thống hoặc dịch vụ khác.


Điều bạn thực sự cần ở đây không phải là điều hành tất cả các công việc cùng một lúc. Thay vào đó, hãy chia chúng thành các đợt và chạy tất cả các công việc trong một đợt cùng một lúc, để chúng kết thúc, sau đó bắt đầu đợt tiếp theo. GNU Parallel ( https://www.gnu.org/software/abul/ ) có thể được sử dụng cho việc này, nhưng nó không lý tưởng ở quy mô đó trong môi trường sản xuất (nếu bạn đi theo nó, đừng quá tích cực, như tôi đã nói, bạn có thể tràn vào mạng và ảnh hưởng đến các hệ thống mà bạn không thể chạm vào). Tôi thực sự khuyên bạn nên xem xét một công cụ điều phối mạng thích hợp như Ansible ( https://www.ansible.com/), vì điều đó sẽ không chỉ giải quyết các vấn đề tương tranh của bạn (Ansible thực hiện theo đợt như tôi đã đề cập ở trên), mà còn cung cấp cho bạn rất nhiều tính năng hữu ích khác để làm việc (như thực thi các nhiệm vụ, báo cáo trạng thái đẹp và tích hợp riêng với một số lượng rất lớn các công cụ khác).


Có nhiều cách để chạy một số lượng hạn chế các tác vụ nền (sử dụng bash, perl, python, et al), theo dõi để hoàn thành nhiệm vụ và chạy nhiều tác vụ hơn khi các tác vụ trước hoàn thành. Một cách tiếp cận đơn giản sẽ là thu thập các lô nhiệm vụ được biểu thị bằng các tệp trong thư mục con và xử lý một lô tại một thời điểm. Có nhiều cách khác ...
ChuckCottrill

Điều này cũng bao gồm các hệ thống giống như unix? Và "GUN song song" là gì?
Biswapriyo

2
@ChuckCottrill Vâng, thực sự có những cách khác có thể được thực hiện. Mặc dù có kinh nghiệm của riêng tôi khi đối phó với loại điều này, nhưng hầu như luôn luôn tốt hơn để có được một công cụ điều phối thực sự hơn là thử và đưa ra giải pháp của riêng bạn, đặc biệt là khi bạn vượt qua vài chục hệ thống về quy mô.
Austin Hemmelgarn


3
@forest Có, bạn có thể sử dụng rlimits để ngăn hệ thống gặp sự cố, nhưng làm cho chúng đúng trong trường hợp như thế này là không dễ dàng (bạn cần phải biết trước yêu cầu tài nguyên cho các nhiệm vụ là gì) và không bảo vệ phần còn lại của mạng từ bất kỳ tác động nào mà các công việc này có thể gây ra (có thể là vấn đề tiềm ẩn lớn hơn nhiều so với sự cố hệ thống cục bộ).
Austin Hemmelgarn

12

Thật khó để nói cụ thể có bao nhiêu trường hợp có thể được chạy như các công việc nền theo cách bạn mô tả. Nhưng một máy chủ bình thường chắc chắn có thể duy trì 700 kết nối đồng thời miễn là bạn thực hiện đúng. Máy chủ web làm điều này mọi lúc.

Tôi có thể đề nghị bạn sử dụng song song GNU ( https://www.gnu.org/software/abul/ ) hoặc một cái gì đó tương tự để thực hiện điều này? Nó sẽ cung cấp cho bạn một số lợi thế của phương pháp công việc nền:

  • Bạn có thể dễ dàng thay đổi số lượng phiên đồng thời.
  • Và nó sẽ đợi cho đến khi phiên hoàn thành trước khi nó bắt đầu phiên mới.
  • Nó dễ dàng hơn để phá thai.

Hãy xem tại đây để bắt đầu nhanh: https://www.gnu.org/software/abul/abul_tutorial.html#A-single-input-source


1
Hấp dẫn! Tôi sẽ xem xét điều này. Bạn có biết nếu thử loại hoạt động này (không có sự trợ giúp của Parallel) sẽ có nguy cơ sụp đổ máy ảo hóa không?
KuboMD

2
@KuboMD nếu bạn có thể đánh sập máy ảo hóa với thứ gì đó quá tầm thường, thì đó là một lỗi trong trình ảo hóa :)
hobbs

như một bên, các máy chủ web thường sử dụng xử lý luồng hoặc xử lý dựa trên sự kiện (ví dụ: gunicorn.org )
ChuckCottrill

10

Sử dụng &để xử lý song song là tốt khi thực hiện một vài và khi bạn theo dõi tiến trình. Nhưng nếu bạn đang chạy trong môi trường sản xuất của công ty, bạn cần thứ gì đó giúp bạn kiểm soát tốt hơn.

ls ~/sagLogs/ | parallel --delay 0.5 --memfree 1G -j0 --joblog my.log --retries 10 foo {}

Điều này sẽ chạy foocho mỗi tập tin trong ~/sagLogs. Nó bắt đầu một công việc cứ sau 0,5 giây, nó sẽ chạy song song nhiều công việc miễn là RAM 1 GB miễn phí, nhưng sẽ tôn trọng các giới hạn trên hệ thống của bạn (ví dụ: số lượng tệp và quy trình). Thông thường, điều này có nghĩa là bạn sẽ chạy song song 250 công việc nếu bạn chưa điều chỉnh số lượng tệp đang mở. Nếu bạn điều chỉnh số lượng tệp đang mở, bạn sẽ không gặp vấn đề gì khi chạy song song 32000 - miễn là bạn có đủ bộ nhớ.

Nếu một công việc thất bại (tức là trả về với mã lỗi), nó sẽ được thử lại 10 lần.

my.log sẽ cho bạn biết nếu một công việc thành công (sau khi có thể thử lại) hay không.


Điều này có vẻ rất hứa hẹn, cảm ơn bạn.
KuboMD

Chạy thử nghiệm đơn giản cat ~/sagLogs/* >> ~/woah | parallelvà thánh moly nhanh. 1.054.552 dòng trong chớp mắt.
KuboMD

3
Lệnh bạn đưa ra có chuyển hướng kép, vì vậy tôi không nghĩ rằng nó thực hiện những gì bạn dự định làm. GNU Parallel có tổng chi phí là 10 ms cho mỗi công việc, vì vậy các công việc 1M sẽ mất theo thứ tự 3 giờ.
Ole Tange

1
Nó hoàn toàn không áp dụng nếu tất cả những gì bạn muốn làm chỉ đơn giản là nối các tệp.
Ole Tange

1
@KuboMD một vòng lặp bận rộn CPU tầm thường như awk 'BEGIN{for(i=rand()*10000000; i<100000000;i++){}}' sẽ hoạt động để chơi xung quanh. Hoặc thử nó trong một nhiệm vụ như sleep 10để thấy nó giữ ncông việc trong chuyến bay mà không sử dụng nhiều thời gian CPU. ví dụ: time parallel sleep ::: {100..1}chạy ngủ từ 100 xuống 1 giây.
Peter Cordes

1

Điều gì xảy ra nếu tôi bắt đầu quá nhiều công việc nền?

hệ thống sẽ trở nên chậm chạp và không phản hồi, trường hợp xấu nhất là không phản hồi, tốt nhất là chỉ cần nhấn nút nguồn và thực hiện khởi động lại một cách khó khăn ... điều này sẽ chạy một cái gì đó như root mà nó có đặc quyền để thoát khỏi điều đó. Nếu kịch bản bash của bạn đang chạy dưới quyền người dùng thường xuyên, sau đó điều đầu tiên mà nói đến cái tâm là /etc/security/limits.conf/etc/systemd/system.confvà tất cả các biến trong đó tới [lý tưởng nói] ngăn chặn người dùng (s) từ quá tải hệ thống.

  • cpu = xeon E5649, đó là cpu 12 lõi ; do đó, bạn có 12 lõi cho 12 quy trình để chạy đồng thời mỗi lõi sử dụng một trong mười hai lõi với tỷ lệ 100%. Nếu bạn khởi động 24 quy trình, thì mỗi quy trình sẽ chạy với mức sử dụng 50% cho mỗi mười hai lõi, 700 quy trình = 1,7% nhưng đó là một máy tính miễn là mọi thứ hoàn thành đúng trong một khoảng thời gian ok thì thành công; hiệu quả không phải lúc nào cũng phù hợp.

    1. Tất cả 700 trường hợp có thể chạy đồng thời? Chắc chắn, 700 không phải là một con số lớn; maxprocVí dụ /etc/security/limits.conf của tôi là 4,135,275 chẳng hạn

    2. Tôi có thể đi bao xa cho đến khi máy chủ của tôi đạt đến giới hạn? Xa hơn 700 tôi chắc chắn.

    3. Giới hạn ... điều gì sẽ xảy ra nếu tập lệnh được khởi động trong tài khoản người dùng [và nói chung là root cũng limits.confáp dụng khá nhiều cho mọi người] là tập lệnh sẽ thoát ra sau khi đã thử thực hiện foo &700 lần; sau đó bạn sẽ thấy 700 quy trình foo với mỗi pid khác nhau nhưng bạn chỉ có thể thấy 456 (lựa chọn số ngẫu nhiên) và 244 khác không bao giờ bắt đầu vì chúng bị chặn bởi một số giới hạn bảo mật hoặc hệ thống.

Câu hỏi triệu đô la: có bao nhiêu bạn nên chạy đồng thời?

có liên quan đến mạng và bạn cho biết mỗi người sẽ thực hiện kết nối telnet, phỏng đoán có giáo dục là bạn sẽ chạy vào giới hạn mạng và chi phí hoạt động trước khi bạn thực hiện giới hạn cpu và ram. Nhưng tôi không biết cụ thể bạn đang làm gì, điều gì có thể xảy ra là bạn có thể khởi động tất cả 700 cùng một lúc, nhưng mọi thứ sẽ tự động chặn cho đến khi các quy trình và kết nối mạng trước đó kết thúc và đóng dựa trên các giới hạn hệ thống khác nhau, hoặc một cái gì đó như 500 đầu tiên sẽ khởi động sau đó 200 còn lại sẽ không vì giới hạn hệ thống hoặc kernel ngăn chặn nó. Nhưng tuy nhiên nhiều người chạy cùng một lúc, sẽ có một chút ngọt ngàotại chỗ để hoàn thành công việc nhanh nhất có thể ... giảm thiểu chi phí và tăng hiệu quả. Là 12 lõi (hoặc 24 nếu bạn có 2 lõi), sau đó bắt đầu với 12 (hoặc 24) cùng một lúc và sau đó tăng số lô đồng thời đó lên 12 hoặc 24 cho đến khi bạn không thấy cải thiện thời gian chạy.

gợi ý: google max telnet kết nối và xem cách này áp dụng cho (các) hệ thống của bạn. Cũng đừng quên về tường lửa. Cũng tính toán nhanh bộ nhớ cần thiết cho mỗi quá trình x 700; đảm bảo <RAM có sẵn (khoảng 50gb trong trường hợp của bạn) nếu không hệ thống sẽ bắt đầu sử dụng SWAP và về cơ bản trở nên không phản hồi. Vì vậy, hãy xử lý 12, 24, N xử lý cùng một lúc và theo dõi RAM miễn phí, sau đó tăng N đã có một số kiến ​​thức về những gì đang xảy ra.

Theo mặc định, RHEL giới hạn số lượng kết nối telnet từ một máy chủ duy nhất xuống còn 10 phiên đồng thời. Đây là một tính năng bảo mật ... được đặt thành 10, /etc/xinetd.conf, thay đổi giá trị của Per perourceource.

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.