2011-11-02 19 views
5

Chúng tôi đang lưu trữ trang web của chúng tôi trong AWS. Hiện tại chúng tôi có 3 trường hợp EC2 trong một cụm, sử dụng cân bằng tải AWS.Làm thế nào để thiết lập một nhiệm vụ CRON để chỉ chạy một lần cho mỗi tập hợp các trường hợp?

Máy chủ có linux, apache, java, mysql và tomcat 6.0.

Chúng tôi đang đưa ra quyết định về cách thiết lập nhiệm vụ để chạy mỗi giờ. Nơi rõ ràng để làm điều này là trong mã Java, nhưng có một vấn đề.

Vấn đề là vì chúng tôi có 3 trường hợp trong cụm (tất cả đều giống nhau), nhiệm vụ sẽ chạy 3 lần trên giờ, thay vì mỗi giờ một lần, một lần cho mỗi trường hợp.

Tôi có một vài ý tưởng để khắc phục điều này nhưng hy vọng rằng có một tiêu chuẩn công nghiệp tốt hơn, có thể là về cách quản lý điều này.

Một ý tưởng là lưu trữ trong DB mà nó đã chạy. Nhiệm vụ sẽ thấy rằng nó đã chạy ngày hôm nay hay không. Tôi thấy lỗi ở đó.

Ý tưởng khác là sử dụng cron được cài đặt trên một trong các phiên bản trong hệ điều hành gốc, bên ngoài mã trong Tomcat. Điều này sẽ sử dụng wget để gọi một trang web mà các cuộc gọi một phương pháp java. Vì đó sẽ chỉ gọi một trong các trường hợp, nó chỉ nên chạy một lần.

Cả hai cách đều có vẻ như hack và dễ bị lỗi. Có cách nào thực sự để làm điều này?

Trả lời

3

Tôi đã sử dụng giải pháp cron/wget và đây thực sự là một cách hợp lý để giải quyết vấn đề. Quản trị viên hệ thống của bạn sẽ đánh giá cao việc có thể kiểm soát nó.

Một giải pháp khác là sử dụng thuộc tính hệ thống JVM để chỉ ra trường hợp nào của bạn là phiên bản chạy công việc. Ví dụ: -DschedulerEnabled=true. Chỉ đặt cờ đó trên một trong các cá thể và có mã lập lịch công việc chỉ chạy nếu cờ đó được đặt.

Cuối cùng, Quartz hỗ trợ giải pháp dựa trên DB của bạn với tính năng Clustering. Ưu điểm của điều này là nó thực sự là một giải pháp HA. Với các giải pháp khác nếu máy hoạt động như công việc lên lịch, bạn phải tự chuyển sang máy khác.

+0

Ngoài ra, chỉ cần tìm thấy rcron mà có thể giải quyết nó là tốt: https://code.google.com/p/rcron/ – razzed

3

Trong khi có câu trả lời được chấp nhận, có một số giải pháp đơn giản, được phát triển trong nước không có lỗi như bạn đã nêu ở trên. Giải pháp wget hoạt động tốt để đảm bảo một máy chủ duy nhất chạy mã, nhưng thêm các vấn đề bảo mật (bạn nên bảo mật URL bằng khóa chia sẻ riêng tư), và như @sourcedelica cũng chỉ ra vấn đề máy chủ nào nên thực sự gọi nhiệm vụ cron.

Tôi có xu hướng tìm giải pháp hoạt động bất kể số lượng hệ thống bạn có - và cũng không yêu cầu cấu hình cron khác nhau cho các hệ thống khác nhau.

Giả định là xuống đường bạn có thể thêm máy mới và máy chủ chính của bạn (máy chủ được cấu hình để chạy tác vụ cron của bạn) có thể bị chết hoặc bị chấm dứt.

Một giải pháp tôi đã phát triển sử dụng ổ khóa cơ sở dữ liệu cụm có thể được thực hiện với một hai bảng đơn giản:

CREATE TABLE `Server` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `uname` varchar(32) NOT NULL, 
    `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    `alive` timestamp NULL DEFAULT NULL, 
    PRIMARY KEY (`id`) 
); 

CREATE TABLE `Lock` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    `code` varchar(128) NOT NULL, 
    `pid` int(10) unsigned DEFAULT NULL, 
    `server` int(10) unsigned DEFAULT NULL, 
    `locked` timestamp NULL DEFAULT NULL, 
    `used` timestamp NULL DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `code` (`code`) 
); 

Mỗi hệ thống có một độc đáo uname, và đăng ký một bản ghi nếu nó không tồn tại; cập nhật alive mỗi lần.

Để có được một khóa:

SELECT * FROM Lock WHERE code='cron-cluster'; 

Nếu nó không tồn tại,

INSERT INTO `Lock` ... 

Một khi bạn đã Lock của bạn với id của 32. Nếu serverpid đều NULL, để họ ra đi đến máy chủ của tôi id và quá trình hiện tại id, sử dụng bản chất nguyên tử của cơ sở dữ liệu để đảm bảo chỉ có một.

UPDATE Lock SET server=1,pid=4233 WHERE id=32 AND server IS NULL and pid IS NULL; 

Sau đó, bạn làm một lựa chọn nữa để xem nếu bạn thực sự mua nó (giả định rằng n máy khác nhau đang cố gắng để có được các khóa cùng một lúc):

SELECT COUNT(id) FROM Lock WHERE code='cron-cluster' AND server=1 AND pid=4233; 

Nếu kết quả là 1 , bạn đã có được khóa, 0 có nghĩa là một quá trình khác đã làm.

Điều cuối cùng cần thiết là yêu cầu mỗi máy chủ xóa sạch khóa chết và máy chủ chết; mỗi máy chủ chịu trách nhiệm kiểm tra xem một quy trình đang hoạt động có đang chạy cho mỗi khóa Lock và khi Server không được cập nhật là alive sau một thời gian nhất định, hãy xóa tất cả các khóa được liên kết với máy chủ đó và bản ghi Server của nó.

tôi đã thêm thuộc tính máy chủ khác vào bảng Server để cho phép giám sát không gian đĩa, CPU vv

Trong khi không mạnh như thạch anh clustering, nó giải quyết vấn đề của bạn.

+0

Yêu công việc của bạn, điều này đã cho tôi cái nhìn sâu sắc tôi đã thiếu để con số nó ra. Tôi đã đi hơi đơn giản hơn, sử dụng MySQL cron có thể chạy ở bất kỳ khoảng thời gian nào, tôi đã đi với 4 giờ: '" UPDATE khóa SET server = 1, lock_date = NOW() WHERE lock_date shazbot

Các vấn đề liên quan