Đăng nhập thông qua một FIFO, sau đó chuyển hướng đến một tập tin?


8

Tôi có một ứng dụng phải đăng nhập từng giao dịch. Mọi thông điệp tường trình đều bị xóa vì chúng ta cần có một bản ghi về những gì đã xảy ra dẫn đến một vụ tai nạn. Các đồng nghiệp của tôi và tôi đã tò mò về cách đạt được hiệu ứng hiệu năng của bộ đệm trong khi đảm bảo rằng thông điệp tường trình đã rời khỏi quy trình.

Những gì chúng tôi đã đưa ra là:

  • tạo một FIFO mà ứng dụng có thể ghi vào và
  • chuyển hướng nội dung của FIFO đó sang một tệp thông thường cat.

Đó là, những gì đã được thông thường:

app --logfile logfile.txt

Hiện tại là:

mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo

Có bất kỳ vấn đề nào về phương pháp này không? Nó hoạt động khi chúng tôi kiểm tra nó, nhưng chúng tôi muốn chắc chắn rằng các tin nhắn sẽ tìm đường đến tệp chuyển hướng ngay cả khi ứng dụng gốc gặp sự cố.

(Chúng tôi không có mã nguồn cho các ứng dụng, do đó lập trình các giải pháp ra khỏi câu hỏi này. Ngoài ra, các ứng dụng sẽ không ghi vào stdout, vì vậy đường ống trực tiếp đến một lệnh khác nhau là ra câu hỏi. Vì vậy, syslogkhông phải là một khả năng .)


Cập nhật: Tôi đã thêm một tiền thưởng. Câu trả lời được chấp nhận sẽ không liên quan loggervì lý do đơn giản đó không phảilogger là điều tôi đã hỏi. Như câu hỏi ban đầu, tôi chỉ tìm kiếm gotchas trong việc sử dụng một bộ xếp hình.


Dường như có một số nhầm lẫn lớn trong một số câu trả lời cho đến nay. Như tôi đã nhấn mạnh ban đầu trong câu hỏi của mình, tôi đang tìm kiếm gotchas cho phương pháp sử dụng FIFO làm trung gian khai thác gỗ . Tôi không quan tâm đến các đề xuất thay thế mà ít nhất là không khám phá các vấn đề cơ bản của câu hỏi ban đầu của tôi.
chrisaycock

Nếu câu trả lời của tôi về việc đăng nhập vào thiết bị xuất chuẩn không phải là hướng bạn quan tâm, có lẽ bạn có thể xóa "Ngoài ra, ứng dụng sẽ không ghi vào thiết bị xuất chuẩn, do đó, việc chuyển trực tiếp sang một lệnh khác không nằm trong câu hỏi" khỏi câu hỏi?
nickgrim

Câu trả lời:


6

Lưu ý rằng fifo thường là cần thiết trong lập trình trong đó số tiền được viết có thể vượt quá số lượng đọc ra.

Như vậy, fifo sẽ không hoạt động hoàn toàn trơn tru như bạn dự đoán nhưng sẽ giải quyết vấn đề chính của bạn trong khi giới thiệu một vấn đề khác.

Có ba hãy cẩn thận.

  1. Viết cho fifo bị chặn vô thời hạn nếu không có gì đang đọc đầu kia khi khởi tạo.
  2. Fifo có chiều rộng cố định là 64K, nếu bộ đệm được lấp đầy bởi điểm đó thì ghi tiếp sẽ bị chặn cho đến khi người đọc bắt kịp.
  3. Người viết đường ống sẽ bị giết bằng SIGPIPE nếu người đọc chết hoặc thoát.

Điều này có nghĩa là vấn đề của bạn (giả lập I / O được đệm trên một bản ghi không được đệm) sẽ được giải quyết. Đó là bởi vì 'giới hạn' mới trên FIFO của bạn sẽ có hiệu lực trở thành tốc độ của bất kỳ tiện ích nào đang ghi những gì trong đường ống vào đĩa (có lẽ sẽ được đệm I / O).

Tuy nhiên, người viết trở nên phụ thuộc vào trình đọc nhật ký của bạn để hoạt động. Nếu người đọc dừng đọc hoàn toàn, người viết sẽ chặn. Nếu trình đọc đột ngột thoát ra (giả sử bạn hết dung lượng đĩa trên mục tiêu), người viết sẽ SIGPIPE và có thể thoát.

Một điểm khác cần đề cập là nếu máy chủ hoảng loạn và kernel ngừng phản hồi, bạn có thể mất tới 64k dữ liệu trong bộ đệm đó.

Một cách khác để khắc phục điều này sẽ là ghi nhật ký vào tmpfs (/ dev / shm trên linux) và nối đầu ra đến một vị trí đĩa cố định. Có ít giới hạn hạn chế hơn đối với việc cấp phát bộ nhớ khi thực hiện việc này (không phải 64K, thường là 2G!) Nhưng có thể không hiệu quả với bạn nếu người viết không có cách nào để mở lại logfiles (bạn sẽ phải xóa nhật ký khỏi tmpfs theo định kỳ). Nếu máy chủ hoảng loạn trong phương pháp này, bạn có thể mất nhiều dữ liệu hơn.


Đó là một số thông tin tốt liên quan /dev/shm. Chúng tôi cũng đã xem xét điều đó, mặc dù nó đã làm tôi mất trí tail -f.
chrisaycock

4
mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo

Điều gì xảy ra khi cat logfifoquá trình của bạn chết, ai đó giết chết nó một cách tình cờ hoặc ai đó vô tình chỉ nó vào vị trí sai?

Kinh nghiệm của tôi là appsẽ nhanh chóng chặn và treo. Tôi đã thử điều này với Tomcat, Apache và một vài ứng dụng xây dựng nhà nhỏ và gặp vấn đề tương tự. Tôi chưa bao giờ điều tra rất xa, bởi vì loggerhoặc chuyển hướng I / O đơn giản đã làm những gì tôi muốn. Tôi thường không cần sự hoàn thiện đăng nhập, đó là những gì bạn đang cố gắng theo đuổi. Và như bạn nói, bạn không muốn logger.

Có một số cuộc thảo luận về vấn đề này tại Linux không chặn fifo (ghi nhật ký theo yêu cầu) .


Hấp dẫn. Vì vậy, các ứng dụng có thể chặn? Chúng tôi đang nghĩ đến việc ném vào khăn và đặt hàng Fusion IO vào thời điểm này.
chrisaycock

Hãy thử một lần. Đối với tôi, kết quả này xảy ra nhanh chóng (trong môi trường thử nghiệm trên phần cứng thông số kỹ thuật thấp). Đây là trên Ubuntu và RedHat 5. Không chắc liệu FreeBSD, v.v. có hành vi tương tự không.
Stefan Lasiewski

2

Các tùy chọn của bạn khá bị giới hạn bởi ứng dụng, nhưng những gì bạn đã thử nghiệm sẽ hoạt động.

Chúng tôi làm một cái gì đó tương tự với véc ni và véc ni để ghi nhật ký ở đâu đó hữu ích cho chúng tôi. Chúng tôi có một fifo và chỉ cần đọc từ nó với syslog-ng và gửi nó ở nơi chúng tôi cần. Chúng tôi xử lý khoảng 50 GB và cho đến nay vẫn chưa có vấn đề gì với cách tiếp cận này


Thật tuyệt, rất vui khi biết chúng tôi không phải là những người duy nhất nghĩ ra điều này.
chrisaycock

2

Môi trường là CentOS và ứng dụng ghi vào một tệp ...

Thay vì gửi đến một tệp thông thường, tôi sẽ gửi đầu ra tới syslog và đảm bảo rằng các thông báo nhật ký hệ thống đang được gửi đến một máy chủ trung tâm cũng như cục bộ.

Bạn sẽ có thể sử dụng tập lệnh shell như thế này:

logger -p daemon.notice -t app < fifo

Bạn cũng có thể lấy đầu vào (đến logger) từ cathoặc từ tail -fvào một đường ống:

tail -f fifo | logger ...
cat fifo | logger ...

Vấn đề duy nhất là nó không phân biệt dựa trên tầm quan trọng của thông điệp tường trình (mọi thứ đều là THÔNG BÁO ) nhưng ít nhất nó được ghi lại và cũng được gửi ra khỏi máy chủ đến một máy chủ trung tâm.

Cấu hình nhật ký hệ thống phụ thuộc vào máy chủ bạn đang sử dụng. Có rsyslogsyslog-ng(cả hai rất có khả năng).

EDIT : Sửa đổi sau khi nhận thêm thông tin từ poster.


Các thông điệp tường trình được ghi vào một tệp mà chúng ta có thể chọn, nhưng ứng dụng sẽ không ghi vào stdout. HĐH là CentOS (Tôi đã gắn thẻ câu hỏi là linux , nhưng tôi đoán rằng rất dễ bỏ lỡ). Tất cả các tin nhắn đều có tầm quan trọng như nhau, vì vậy không có sự khác biệt giữa thông báo và lỗi trong ứng dụng này.
chrisaycock

Không có sự khác biệt giữa một thông báo và một lỗi? Oh thực sự ? Không có sự khác biệt giữa Slow query detectedDatabase halted?
Mei

(Tôi đã cập nhật bài viết.)
Mei

1

Bạn viết:

Ngoài ra, ứng dụng sẽ không ghi vào stdout...

Bạn đã thử đăng nhập vào "tập tin" /dev/stdoutchưa? Điều đó có thể cho phép bạn làm một cái gì đó như:

app --logfile /dev/stdout | logger -t app

Điều đó có khác với một FIFO không? Gotchas là gì? Tôi không tìm kiếm một sự thay thế, mỗi người ; Tôi đang tìm kiếm cái nhìn sâu sắc về cách tiếp cận tôi đã liệt kê là mạnh mẽ. Đó là tất cả những gì tôi quan tâm.
Chrisaycock

1
Vâng, nó khác với một FIFO; về cơ bản nó là một tập tin được kết nối với STDOUT. Vì vậy, bạn có thể sử dụng điều đó để đăng nhập vào STDOUT và từ đó để syslog hoặc tương tự. Nó được dự định là một giải pháp cho vấn đề ban đầu của bạn, nhưng hy vọng sẽ mạnh mẽ hơn một phần trăm do có ít bộ phận chuyển động hơn.
nickgrim

1

Không có điểm nào để ghi vào fifo và sau đó có một quy trình khác ghi nó vào một tệp. Chỉ cần ghi trực tiếp vào tệp một cách bình thường và một khi write()trả về, nó nằm trong tay kernel; nó vẫn sẽ ghi nó vào đĩa nếu ứng dụng gặp sự cố.


Mỗi thông điệp tường trình được tuôn ra : đây là chặn ghi. Chúng tôi không có quyền kiểm soát nào vì chúng tôi không có mã nguồn của ứng dụng.
chrisaycock

@chrisaycock, phải ... vậy vấn đề ở đâu?
psusi

Các đồng nghiệp của tôi và tôi đã tò mò về cách đạt được hiệu ứng hiệu năng của bộ đệm trong khi đảm bảo rằng thông điệp tường trình đã rời khỏi quy trình.
chrisaycock

@chrisaycock, ohh, vì vậy ứng dụng hiện đang sử dụng O_SYNC hoặc fsync()chờ mỗi lần ghi vào đĩa và bạn KHÔNG muốn điều đó xảy ra (có nguy cơ bị mất trong trường hợp xảy ra sự cố hệ thống)?
psusi

1
@chrisaycock, nó không liên quan gì đến giao diện của ổ đĩa, nó thường chỉ có nghĩa là kernel đã sao chép nó vào bộ đệm của hệ thống tập tin (và ngoài ứng dụng). Như tôi đã nói trong câu trả lời ban đầu của mình, một khi write()đã trả về, ứng dụng có thể sập tất cả những gì nó thích - dữ liệu sẽ đưa nó vào đĩa miễn là kernel không gặp sự cố.
psusi
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.