2011-07-12 29 views
6

Tôi vừa viết một loạt các lớp gửi email hàng loạt để xử lý lượng email khổng lồ và phân tích cú pháp nội dung của chúng theo các thông số đã qua. Nếu tôi kiểm tra email trên 1000 người nhận ngẫu nhiên và 1000 người gửi ngẫu nhiên từ cơ sở dữ liệu của tôi, cho đến thời điểm tập lệnh chạm vào phần send() (tôi đã nhận xét), tôi nhận được hiệu suất khoảng 2 giây và bộ nhớ cao nhất 20 MB , điều đó thật tuyệt.PHP, sendmail và vận chuyển - cách tăng tốc độ gửi thư

Tuy nhiên, nếu tôi bỏ ghi chú phần gửi, quá trình gửi mất 30 giây. Điều này là không thể chấp nhận được, và tôi muốn tăng tốc nó bằng cách nào đó. Rõ ràng là từ thử nghiệm rằng sự chậm trễ là do không có gì khác hơn so với cuộc gọi $ mail-> send(), như thể nó đang chờ nó trả lại một cái gì đó trước khi tiếp tục vòng lặp và gửi email tiếp theo.

Điều tôi đang thắc mắc là: làm thế nào để tăng tốc độ gọi send()? Tôi có thể làm gì để làm cho nó nhanh hơn? Tôi đã thử sử dụng hai phương thức gửi:

  1. Zend Truyền tải SMTP, kết nối trực tiếp với máy chủ và chỉ gửi. Điều này mất 30 giây cho mỗi 1000 email.
  2. Sendmail qua Zend_Mail. Chỉ cần gọi hàm gửi của Zend_Mail sau khi chuẩn bị từng email. Điều này mất 60 giây.

Xin lưu ý rằng xếp hàng chắc chắn là một tùy chọn và tôi đã xây dựng nó vào các lớp học của mình. Tất cả phải mất là kích hoạt một cron và nó hoạt động như một say mê. Nhưng tôi tự hỏi về việc gửi thực tế và làm thế nào để tăng tốc độ đó. Vì vậy, thực tế gửi() gọi.

Trả lời

2

Tôi muốn lưu các thư trong một thư mục và gửi chúng bằng một kịch bản shell (cron/daemon/...):

Zend_Mail::setDefaultTransport(
    new Zend_Mail_Transport_File(
     array(
      'path' => __DIR__, 
      'callback' => function() { 
       do { 
        $file = 'email-' . date('Y-m-d_H-i-s') . '_' . mt_rand() . '.eml'; 
       } while (file_exists($file)); 
       return $file; 
      }, 
     ) 
    ) 
); 
+0

Sửa lỗi nếu tôi sai, nhưng một truy vấn MySQL tốt sẽ luôn vượt qua việc đọc tệp. Cơ chế xếp hàng đã được thực hiện theo cách nào đó và không cần cải thiện ngay bây giờ. Tương tự, các email của chúng tôi đều có nội dung khác nhau. Vì vậy, trong khi chúng tôi đang gửi 1000 email trong 2 giây, mỗi email có một người nhận khác nhau, người gửi khác nhau và nội dung khác nhau. Tôi tin rằng khía cạnh này bạn hiển thị ở đây có thể hữu ích trong việc gửi email hàng loạt, đúng không? Trường hợp nội dung giống hệt nhau trong tất cả các tin nhắn? Nếu không, câu hỏi vẫn còn - điều này có thể nhanh hơn xếp hàng trong cơ sở dữ liệu không? Tôi hoài nghi. – Swader

+0

Tôi nghĩ rằng vấn đề là SENDING không phát sinh! :) Có thể có một số máy chủ thư được tối ưu hóa, có thể tải các gazzilions hàng loạt của thư. Anycase - nó sẽ nhanh hơn phương thức sendmail của php. Truy cập máy chủ trực tiếp nên được nhiều lần fater hơn php sẽ bao giờ được (nó có thể ví dụ sử dụng kết nối liên tục). –

+0

Hmmm, hoàn toàn đúng. Một email chuẩn bị có thể dễ dàng được lưu vào đĩa ở định dạng eml, và từ đó trên một kịch bản sẽ tiếp quản. Điều này cũng có thể phục vụ như một hàng đợi thay thế. Bạn có bất kỳ ví dụ về việc này đang được thực hiện một cách hiệu quả? Tôi rất muốn có một cái nhìn tại một số. – Swader

2

Bạn sẽ cần tăng tốc độ MTA trên máy chủ. Tôi khuyên bạn nên Postfix và bạn thực sự đọc trên mỗi thiết lập để bạn biết làm thế nào để tinh chỉnh nó. Đối với một giải pháp thương mại tôi đã nghe PowerMTA là một lựa chọn tốt nhưng tôi chưa bao giờ thử nó bản thân mình.

Chỉ có rất nhiều hiệu suất bạn có thể ép ra khỏi một máy, nhưng một máy chủ chuyên dụng thường xuyên sẽ có thể cung cấp một lượng thư khá ấn tượng khi bạn đã định cấu hình chính xác. Các nút cổ chai hiệu suất lớn nhất thường là ổ đĩa nơi lưu trữ hàng đợi thư, vì vậy hãy xem xét sử dụng SAS (10k hoặc thậm chí 15k RPM) hoặc ổ đĩa SSD.

+0

tôi chắc chắn sẽ xem xét này. Sản lượng email của chúng tôi sẽ tăng lên đáng kể rất sớm, và một bước tiến như vậy có thể khá cần thiết. – Swader

+0

Chúng tôi đã bắt đầu lập kế hoạch cho phương pháp này, nhưng chúng tôi cũng sẽ đưa câu trả lời của Tomas vào giải pháp của chúng tôi. Nó đã thực sự chứng minh vô cùng tuyệt vời, cho đến nay. – Swader

0

Bạn có thể thử tìm hiểu hàm PHP pcntl-fork. Vì vậy, bạn có thể để lại quá trình gửi trong quá trình khác trong khi phân tích cú pháp email tiếp theo.

KẾ HOẠCH B

Bạn có thể serialize và lưu các đối tượng email vào một hàng đợi cơ sở dữ liệu và để cho kịch bản khác để gửi cho họ ở chế độ nền. Tập lệnh này có thể chạy trong vòng lặp vô hạn (while true) với một số sleep trên mỗi lần lặp lại. Bạn thậm chí có thể chạy nhiều phiên bản của tập lệnh này, nhưng hãy chắc chắn rằng hai tập lệnh sẽ không bắt đầu gửi cùng một email cùng một lúc.

Để đảm bảo rằng tập lệnh vẫn đang chạy, bạn có thể sử dụng monit trên máy Unix. Nó có thể bắt đầu kịch bản nếu dụ cũ đã thất bại vì một lý do nào đó.

+0

Hmm, điều này có vẻ rất hấp dẫn, nhưng nó không phải là một thực tế rằng các chức năng PCNTL không có sẵn nếu PHP được chạy như một mô-đun Apache? Tôi dường như nhớ lại một cái gì đó về điều đó ở đâu đó, nhưng không thể tìm thấy thông tin nữa. Ngoài ra, PCTNL không khả dụng trên các máy Windows và tôi phát triển ứng dụng này trên tất cả các loại hệ điều hành, tùy thuộc vào vị trí của tôi tại một thời điểm cụ thể .. – Swader

+0

Đã thêm gói B. – Gedrox

+0

Tôi đã sử dụng loại xếp hàng này. Dữ liệu email được tuần tự hóa và lưu vào DB với ưu tiên đã cho. Các cronjob sau đó xử lý việc gửi định kỳ bằng cách lấy 500 của các email ưu tiên hàng đầu mỗi 15 phút, và nó có vẻ là tất cả tốt. Nhưng những gì tôi thực sự muốn chỉ là tăng tốc độ gửi() chức năng, và một máy chủ chuyên dụng có lẽ sẽ chỉ là giải pháp duy nhất và tốt nhất dài hạn. – Swader