2008-08-25 40 views
5

Tại công việc của tôi, tôi có một loạt dịch vụ Windows mà tôi chịu trách nhiệm, được viết bằng C# 2003. Mỗi dịch vụ này có bộ hẹn giờ kích hoạt mỗi phút hoặc lâu hơn, nơi phần lớn công việc xảy ra. Vấn đề của tôi là, khi các dịch vụ này chạy, chúng bắt đầu tiêu tốn nhiều thời gian CPU hơn qua mỗi lần lặp, ngay cả khi không có công việc có ý nghĩa cho chúng (tức là chúng chỉ chạy không tải, xem qua cơ sở dữ liệu để làm gì đó). Khi chúng khởi động, mỗi dịch vụ sử dụng mức trung bình (khoảng) 2-3% của 4 CPU, điều này là tốt. Sau 24 giờ, mỗi dịch vụ sẽ tiêu thụ toàn bộ bộ xử lý trong suốt thời gian chạy vòng lặp của nó.Dịch vụ Windows Tăng mức tiêu thụ CPU

Có ai giúp được không? Tôi đang thua lỗ vì những gì có thể gây ra điều này. Giải pháp hiện tại của chúng tôi là khởi động lại các dịch vụ một lần một ngày (họ tự đóng cửa, sau đó một kịch bản thấy rằng họ đang ngoại tuyến và khởi động lại chúng vào khoảng 3 giờ sáng). Nhưng đây không phải là giải pháp lâu dài; mối quan tâm của tôi là khi các dịch vụ trở nên bận rộn, khởi động lại mỗi ngày một lần có thể không đủ ... nhưng khi có hình phạt khởi động đáng kể (tất cả đều sử dụng NHibernate để truy cập dữ liệu), khi chúng bận rộn hơn, chính xác thì chúng tôi don ' t muốn làm là khởi động lại chúng thường xuyên hơn.


@akmad: Đúng, rất khó.

  1. Có, dịch vụ được chạy riêng sẽ hiển thị cùng một triệu chứng theo thời gian.
  2. Không, không. Chúng tôi đã xem xét điều đó. Điều này có thể xảy ra lúc 10 giờ sáng hoặc 6 giờ tối hoặc vào giữa đêm. Không có sự nhất quán.
  3. Chúng tôi làm; và họ là. Các dịch vụ đang làm chính xác những gì họ cần, và không có gì khác. Thật không may, điều đó đòi hỏi sự hiểu biết chính xác khi nào các dịch vụ sắp hết CPU, điều này xảy ra theo một lịch trình khó lường, và không bao giờ nhanh chóng ... điều này khiến cho mọi thứ trở nên khó khăn gấp đôi, bởi vì sếp của tôi sẽ chạy và khởi động lại khi họ bắt đầu gặp sự cố mà không cần suy nghĩ về các sự cố gỡ lỗi.
  4. Không, họ đang sử dụng một lượng RAM khá nhất quán (khoảng 60-80MB mỗi chiếc, ngoài 4GB trên máy).

Đề xuất tốt, nhưng hãy yên tâm, chúng tôi đã thử tất cả các cách khắc phục sự cố thông thường. Những gì tôi hy vọng là đây là một vấn đề .NET mà ai đó có thể biết, mà chúng ta có thể giải quyết. Giải pháp của sếp của tôi (mà tôi nhấn mạnh không muốn thực hiện) là đặt một trường trong cơ sở dữ liệu chứa nhiều lần để các dịch vụ khởi động lại trong ngày, để anh ta có thể làm cho vấn đề biến mất và không nghĩ về nó . Tôi đang tuyệt vọng tìm kiếm nguyên nhân của vấn đề thực sự để tôi có thể sửa chữa nó, bởi vì giải pháp đó sẽ trở thành thảm họa trong khoảng sáu tháng.


@Yaakov Ellis: Mỗi loại đều có chức năng khác nhau. Một lần đọc các bản ghi ra khỏi một cơ sở dữ liệu Oracle ở một nơi nào đó bên ngoài; một quy trình khác xử lý các bản ghi đó và chuyển các tệp thuộc về các bản ghi đó sang hệ thống của chúng tôi; một phần ba kiểm tra các tệp đó để đảm bảo chúng là những gì chúng tôi mong đợi; khác là một dịch vụ bảo trì liên tục kiểm tra những thứ như không gian đĩa (mà chúng tôi có đủ) và thăm dò các máy chủ khác để đảm bảo chúng còn sống; một cái chỉ chạy để đảm bảo tất cả những cái khác đang chạy và thực hiện công việc, theo dõi và báo cáo lỗi, và khởi động lại bất cứ thứ gì không thể giữ cho toàn bộ hệ thống hoạt động 24 giờ một ngày.Vì vậy, nếu bạn đang hỏi những gì tôi nghĩ rằng bạn đang yêu cầu, không có, không có một điều phổ biến mà tất cả các dịch vụ này làm (khác với truy cập cơ sở dữ liệu thông qua NHibernate) mà tôi có thể trỏ đến như là một vấn đề tiềm năng . Thật không may, nếu điều đó hóa ra lại là vấn đề thực sự (điều đó sẽ không làm tôi ngạc nhiên), toàn bộ điều có thể bị vặn - và tôi sẽ kết thúc viết lại tất cả chúng trong SQL đơn giản. Tôi hy vọng đó là một vấn đề thu gom rác hoặc một cái gì đó dễ dàng hơn để đối phó với NHibernate.


@Joshdan: Không bí mật. Như tôi đã nói, chúng tôi đã thử tất cả các cách khắc phục sự cố thông thường. Profiling là vô ích: profiler chúng tôi sử dụng không thể trỏ đến bất kỳ mã nào thực sự thực thi khi mức sử dụng CPU cao. Các dịch vụ này đã bị xé toạc khoảng một tháng trước đây để tìm kiếm vấn đề này. Mỗi phần mã được phân tích để cố gắng tìm hiểu xem mã của chúng tôi có phải là vấn đề hay không; Tôi không ở đây vì tôi không làm bài tập ở nhà. Đây có phải là một trường hợp đơn giản của các dịch vụ thực hiện nhiều công việc hơn dự đoán, đó là điều gì đó đã bị bắt.

Vấn đề ở đây là, hầu hết thời gian, dịch vụ không làm gì cả, nhưng vẫn quản lý tiêu thụ 25% hoặc nhiều hơn bốn nhân CPU: họ không tìm được việc gì và thoát khỏi lặp lại và đợi cho lần lặp tiếp theo. Điều này nên, theo nghĩa đen, hầu như không có thời gian CPU nào cả.

Dưới đây là ví dụ về hành vi mà chúng ta đang thấy, trên một dịch vụ không có việc phải làm trong hai ngày (trong môi trường không thay đổi). Ảnh này đã được chụp tuần trước:

Ngày 1, 8AM: Trung bình Mức sử dụng CPU xấp xỉ 3%
Ngày 1, 6 giờ chiều: Trung bình Mức sử dụng CPU xấp xỉ 8%
Ngày 2, 7 SA: Trung bình. Mức sử dụng CPU xấp xỉ 20%
Ngày 2, 11AM: Trung bình Việc sử dụng CPU xấp xỉ 30%

Sau khi xem xét tất cả những lý do có thể xảy ra, tôi đã hỏi câu hỏi này tại đây. Tôi đã tìm ra câu trả lời sáng tạo hơn (như Ubiguchi)), hoặc con trỏ đến những điều tôi không phải là suy nghĩ (như đề xuất của Ian).


Vì vậy, hiện các cành CPU xảy ra ngay trước khi gọi lại timer , trong giờ gọi lại, hoặc ngay sau khi hẹn giờ gọi lại?

Bạn hiểu lầm. Đây không phải là một cành. Nếu có, sẽ không có vấn đề gì; Tôi có thể đối phó với gai. Nhưng nó không ... việc sử dụng CPU đang đi lên nói chung. Ngay cả khi dịch vụ không làm gì cả, hãy đợi đến lần hẹn giờ tiếp theo. Khi dịch vụ khởi động, mọi thứ đều tốt đẹp và bình tĩnh, và đồ thị trông giống như những gì bạn mong đợi ... nói chung, 0% mức sử dụng, với mức tăng 10% khi NHibernate truy cập cơ sở dữ liệu hoặc dịch vụ có một số lượng công việc nhỏ . Nhưng điều này tăng lên 25% trên toàn diện (nhiều hơn nếu tôi để nó đi quá xa) việc sử dụng mọi lúc trong khi quá trình đang chạy.

Điều đó làm cho Ian đề xuất viên đạn bạc hợp lý (NHibernate không rất nhiều nội dung khi bạn không tìm kiếm). Than ôi, tôi đã thực hiện giải pháp của mình, nhưng nó không có hiệu lực (tôi không có bằng chứng về điều này, nhưng tôi thực sự nghĩ rằng nó làm mọi thứ tồi tệ hơn ... sử dụng trung bình là dường như để tăng nhanh hơn bây giờ).Lưu ý rằng việc loại bỏ phần "NHibernate" NHibernate (như bạn đề nghị) là không khả thi, vì điều đó sẽ loại bỏ khoảng 90% mã trong dịch vụ, điều này sẽ cho phép tôi loại bỏ bộ hẹn giờ như một vấn đề (mà tôi hoàn toàn có ý định thử), nhưng không thể giúp tôi loại trừ NHibernate là vấn đề, bởi vì nếu NHibernate đang gây ra điều này, sau đó sửa chữa dodgy đó là thực hiện (xem bên dưới) chỉ là sẽ phải trở thành The Way The System Works; chúng tôi rất phụ thuộc vào NHibernate cho dự án này rằng PM chỉ đơn giản là sẽ không chấp nhận rằng nó gây ra một vấn đề cấu trúc không thể giải quyết.

Tôi chỉ lưu ý một cảm giác tuyệt vọng trong câu hỏi - đó là vấn đề của mình sẽ tiếp tục chặn một phép lạ nhỏ

Đừng có nghĩa là cho nó để đi tắt như vậy. Hiện tại, các dịch vụ đang được khởi động lại hàng ngày (với tùy chọn nhập bất kỳ số giờ nào trong ngày để tắt máy và khởi động lại), sẽ khắc phục sự cố nhưng không thể là giải pháp lâu dài khi chúng đi vào máy sản xuất và bắt đầu trở nên bận rộn. Các vấn đề sẽ không tiếp tục, cho dù tôi sửa chúng hay PM vẫn duy trì ràng buộc này đối với chúng. Rõ ràng, tôi muốn thực hiện một sửa chữa thực sự, nhưng kể từ khi thử nghiệm ban đầu cho thấy không có lý do cho điều này, và các dịch vụ đã được xem xét rộng rãi, các PM sẽ chỉ có họ khởi động lại nhiều lần hơn dành nhiều thời gian cố gắng sửa chữa chúng . Đó là hoàn toàn ngoài tầm kiểm soát của tôi và làm cho phép màu bạn đang nói về quan trọng hơn nó sẽ khác.

Điều đó cực kỳ hấp dẫn (trong phạm vi số khi bạn tin tưởng tiểu sử của mình).

Tôi không. Nhưng sau đó, đây là những dịch vụ Windows được viết bằng .NET 1.1 chạy trên một máy Windows 2000, được triển khai bởi một kịch bản Nant tồi tệ, sử dụng một phiên bản cũ của NHibernate để truy cập cơ sở dữ liệu. Có rất ít trên máy đó tôi thực sự sẽ nói rằng tôi tin tưởng.

+0

Có thể cho bộ hẹn giờ dịch vụ của bạn hoạt động nhiều hơn mức cần thiết không? Nói, bộ đếm thời gian được kích hoạt và vòng lặp chưa được thực hiện, và 2 minuets đã qua. Bộ hẹn giờ có được kích hoạt lại không? Rất nhiều thứ có thể sai nhưng tất cả đều liên quan đến mã của bạn. Đây không phải là hành vi bình thường của dịch vụ. – Jaywalker

+0

Bạn có bất kỳ mã nào phát hiện xem dịch vụ có còn "hoạt động" trong chu kỳ làm việc trước đó không? – hova

Trả lời

2

Nó rõ ràng là khá khó khăn để từ xa gỡ lỗi bạn ứng dụng chưa được biết ... nhưng đây là một số những điều tôi muốn xem xét:

  1. gì xảy ra khi bạn chỉ chạy một trong những dịch vụ tại một thời điểm? Bạn vẫn thấy tốc độ chậm không? Điều này có thể chỉ ra rằng có một số tranh chấp giữa các dịch vụ.
  2. Sự cố luôn xảy ra cùng một lúc, bất kể dịch vụ đã chạy bao lâu? Điều này có thể chỉ ra rằng một cái gì đó khác (một bản sao lưu, quét virus, vv) đang làm cho toàn bộ máy (hoặc db) bị chậm lại.
  3. Bạn có đăng nhập hoặc một số cơ chế khác để đảm bảo rằng dịch vụ chỉ hoạt động bình thường như bạn nghĩ?
  4. Nếu bạn có thể thấy sự xuống cấp hiệu suất trong một khoảng thời gian ngắn, hãy thử chạy dịch vụ trong một thời gian và sau đó đính kèm một trình thông báo để xem chính xác những gì đang chốt CPU.
  5. Bạn không đề cập gì về việc sử dụng bộ nhớ. Bạn có bất kỳ thông tin nào trong số các dịch vụ này không? Có thể bạn đang sử dụng hết RAM và làm cho ổ đĩa bị hỏng hoặc một số vấn đề tương tự.

Chúc bạn may mắn!

1

'Sợ câu trả lời này sẽ chỉ đề xuất một số hướng dẫn để bạn nhìn vào, nhưng gặp vấn đề tương tự trong .NET Windows Services Tôi có một vài suy nghĩ bạn có thể thấy hữu ích.

Đề xuất đầu tiên của tôi là các dịch vụ của bạn có thể có một số lỗi trong cách xử lý bộ nhớ hoặc có thể trong cách chúng xử lý bộ nhớ không được quản lý. Lần cuối cùng tôi theo dõi một vấn đề tương tự nó bật ra một bên thứ ba OSS libray chúng tôi đã sử dụng được lưu trữ xử lý cho các đối tượng không được quản lý trong bộ nhớ tĩnh. Dịch vụ càng chạy càng lâu thì dịch vụ được chọn càng làm cho quá trình xử lý CPU của quá trình hoạt động rất nhanh. Cách để thử và giải quyết vấn đề này để đảm bảo các dịch vụ của bạn lưu trữ không có gì trong bộ nhớ giữa các lời gọi hẹn giờ, mặc dù các thư viện bên thứ 3 của bạn sử dụng bộ nhớ tĩnh, bạn có thể phải làm điều gì đó thông minh như tạo miền ứng dụng cho yêu cầu hẹn giờ và mương ứng dụng doamin (và bộ nhớ tĩnh của nó) sau khi quá trình xử lý hoàn tất.

Sự cố khác mà tôi đã thấy trong các trường hợp tương tự là mã đồng bộ hóa hẹn giờ bị nghi ngờ, có hiệu lực cho phép nhiều hơn một chuỗi chạy mã xử lý cùng một lúc. Khi chúng tôi gỡ lỗi mã, chúng tôi đã tìm thấy chuỗi thứ nhất đã chặn thứ 2 và vào thời điểm lần thứ 2 bị khởi động thì đó là lần thứ 3 bị chặn. Theo thời gian, việc chặn đã kéo dài lâu hơn và lâu hơn và do đó việc sử dụng CPU đã dẫn đầu. Giải pháp chúng tôi đã sử dụng để khắc phục sự cố là triển khai mã đồng bộ hóa phù hợp để bộ tính giờ chỉ khởi động một chuỗi khác nếu nó không bị chặn.

Hy vọng điều này sẽ hữu ích, nhưng xin lỗi trước mặt nếu cả hai suy nghĩ của tôi đều là màu đỏ.

+0

Việc phân luồng không phải là vấn đề; đó là điều tôi đã xử lý khoảng 18 tháng trước, và tôi tin rằng chỉ có một cuộc gọi hẹn giờ đang chạy vào bất kỳ thời điểm nào. Mặc dù vậy, suy nghĩ tốt, cảm ơn bạn.Tôi sẽ nhìn vào bit AppDomain. Mặc dù tôi không biết về bất kỳ vấn đề bộ nhớ nào, nếu tôi chỉ có thể bỏ qua toàn bộ bối cảnh thực thi sau mỗi lần hẹn giờ, điều đó có thể giết chết bất kỳ vấn đề nào chúng tôi đang gặp phải. Cảm ơn những lời đề nghị. – TheSmurf

1

Âm thanh như một vấn đề về luồng với bộ hẹn giờ. Bạn có thể có một đơn vị công việc ngăn chặn một hoạt động khác đang chạy trên các chuỗi công việc khác nhau, khiến chúng xếp chồng lên nhau mỗi khi bộ hẹn giờ kích hoạt. Hoặc bạn có thể có trường hợp sống và làm việc lâu hơn bạn mong đợi.

Tôi khuyên bạn nên tái cấu trúc bộ hẹn giờ. Thay thế nó bằng một luồng duy nhất xếp hàng hoạt động trên ThreadPool. Bạn có thể Ngủ() chuỗi để kiểm soát tần suất tìm kiếm công việc mới. Đảm bảo đây là nơi duy nhất mã của bạn được đa luồng. Tất cả các đối tượng khác cần được khởi tạo vì công việc được chuẩn bị sẵn sàng để xử lý và bị phá hủy sau khi hoàn thành công việc. STATE LÀ ENEMY trong mã đa luồng.

Khu vực khác nơi thiết kế thiếu sót có vẻ như bạn có nhiều dịch vụ đang thăm dò tài nguyên để làm điều gì đó. Tôi muốn đề nghị hợp nhất chúng dưới một dịch vụ duy nhất. Họ có thể làm những việc riêng biệt, nhưng họ làm việc đồng loạt; bạn chỉ sử dụng hệ thống tập tin, cơ sở dữ liệu, vv để thay thế cho các cuộc gọi phương thức. Ngoài ra, năm 2003? Tôi lấy làm tiếc cho bạn.

+0

Cảm ơn vì điều đó. Thật không may, tôi không có quyền kiểm soát bao nhiêu dịch vụ đang chạy. Tôi hoàn toàn đồng ý rằng hầu hết điều này nên được củng cố. Thật không may, PM là thuyết phục rằng chạy sáu dịch vụ để làm công việc này là hiệu quả hơn. : Tôi cũng đã được harping về việc nâng cấp lên một phiên bản .NET mới trong khoảng hai năm. Điều đó không có hiệu lực. Và bây giờ chúng tôi có nhiều mã hơn (hầu hết là ASP.NET), điều này sẽ làm cho việc nâng cấp thậm chí còn khó khăn hơn khi tôi đề xuất nó lần đầu tiên. Tôi khá tự tin rằng công việc không được xếp chồng lên nhau. Nếu một dịch vụ đã hoạt động khi bộ hẹn giờ của nó bị cháy, th – TheSmurf

2

Tôi đề xuất để hack vấn đề thành nhiều phần.
Đầu tiên, hãy tìm cách tái tạo vấn đề 100% thời gian và nhanh chóng. Giảm bộ hẹn giờ để các dịch vụ có thể phát sinh thường xuyên hơn (ví dụ, nhanh gấp 10 lần bình thường). Nếu vấn đề phát sinh nhanh hơn gấp 10 lần, thì nó liên quan đến số lần lặp lại chứ không liên quan đến thời gian thực hoặc công việc thực được thực hiện bởi các dịch vụ). Và bạn sẽ có thể thực hiện các bước tiếp theo nhanh hơn một lần mỗi ngày.
Thứ hai, nhận xét tất cả mã công việc thực và chỉ để các dịch vụ, bộ hẹn giờ và cơ chế đồng bộ hóa. Nếu sự cố vẫn hiển thị, nó sẽ nằm trong phần mã đó. Nếu không, sau đó bắt đầu thêm lại mã bạn đã nhận xét, mỗi lần một đoạn. Cuối cùng, bạn nên tìm hiểu phần nào của mã đang gây ra sự cố.

3

Bạn nói rằng bạn đang sử dụng NHibernate - (? Chẳng hạn như khi kết thúc mỗi lần lặp) mà bạn đang đóng cửa phiên NHibernate tại điểm thích hợp

Nếu không, sau đó kích thước của bản đồ đối tượng được nạp vào bộ nhớ sẽ được tăng dần theo thời gian, và mỗi phiên tuôn ra sẽ mất nhiều thời gian CPU hơn.

+0

Tôi không tin là chúng tôi đang có. Đó là một phần của một mô hình trong phát triển liên quan đến NHibernate của chúng tôi. Phiên nằm xung quanh trong một thời gian dài. Đó là một khả năng thú vị, cảm ơn bạn. – TheSmurf

0

Đề xuất tốt, nhưng hãy yên tâm, chúng tôi đã thử tất cả các cách khắc phục sự cố thông thường. Những gì tôi hy vọng là đây là một vấn đề .NET mà ai đó có thể biết, mà chúng ta có thể giải quyết.

Cảm giác của tôi là bất kể nguyên nhân cơ bản kỳ quái như thế nào, các bước khắc phục sự cố thông thường là cách tốt nhất để xác định vấn đề.

Vì đây là vấn đề về hiệu suất nên các phép đo tốt là vô giá. Việc sử dụng CPU quá trình tổng thể là quá rộng một phép đo. Ở đâu dịch vụ của bạn có dành thời gian của nó không? Bạn có thể sử dụng một profiler để đo lường điều này, hoặc chỉ cần đăng nhập phần khác nhau bắt đầu và dừng lại. Nếu bạn không thể làm được điều đó, thì hãy sử dụng đề xuất của Andrea Bertani - cô lập các phần bằng cách loại bỏ các phần khác.

Khi bạn đã tìm được khu vực chung, bạn có thể thực hiện các phép đo thậm chí còn tốt hơn, cho đến khi bạn phân loại nguồn gốc của việc sử dụng CPU. Nếu nó không rõ ràng làm thế nào để sửa chữa nó vào thời điểm đó, bạn ít nhất có đạn cho một câu hỏi cụ thể hơn nhiều.

Nếu bạn thực tế đã thực hiện tất cả các khắc phục sự cố thông thường này, vui lòng cho chúng tôi biết về bí mật.

3

Đây là nơi tôi muốn bắt đầu:

  1. Nhận Process Explorer và hiển thị% Thời gian trong JIT,% Thời gian trong GC, Cycles CPU Delta, CPU Time, CPU%, và Chủ đề.
  2. Bạn cũng sẽ muốn hạt nhân và thời gian người dùng, và một vài dấu vết ngăn xếp đại diện nhưng tôi nghĩ bạn phải nhấn Thuộc tính để nhận ảnh chụp nhanh.
  3. So sánh trước và sau khi chụp.

Một vài suy nghĩ về khả năng:

  • GC quá mức (.% Thời gian trong GC đi lên Ngoài ra, Perfmon GC và quầy CPU sẽ tương ứng)
  • đề quá mức và chuyển mạch bối cảnh liên quan (# của các chủ đề đi lên)
  • bỏ phiếu (dấu vết ngăn xếp liên tục bị bắt trong một hàm duy nhất)
  • thời gian hạt nhân quá mức (thời gian hạt nhân cao - Trình quản lý tác vụ hiển thị số thời gian hạt nhân lớn khi CPU cao)
  • ngoại lệ (tab PE .NET Trường hợp ngoại lệ được ném cao và cao hơn. Ngoài ra còn có một bộ đếm Perfmon)
  • vi-rút/rootkit (OK, đây là trường hợp mương cuối cùng - nhưng có thể xây dựng một bộ rootkit ẩn khỏi TaskManager. Tôi nghi ngờ rằng bạn có thể phân bổ mức sử dụng CPU không thể tránh khỏi của mình cho một Bên cạnh đó, nếu bạn đã loại trừ tất cả những điều trên, tôi đã hết ý tưởng ngay bây giờ)
Các vấn đề liên quan