Chạy nhiệm vụ PHP không đồng bộ


144

Tôi làm việc trên một ứng dụng web khá lớn và phần phụ trợ chủ yếu bằng PHP. Có một số vị trí trong mã mà tôi cần hoàn thành một số tác vụ, nhưng tôi không muốn làm cho người dùng chờ kết quả. Ví dụ: khi tạo một tài khoản mới, tôi cần gửi cho họ một email chào mừng. Nhưng khi họ nhấn nút 'Hoàn tất đăng ký', tôi không muốn khiến họ đợi cho đến khi email thực sự được gửi, tôi chỉ muốn bắt đầu quá trình và trả lại tin nhắn cho người dùng ngay lập tức.

Cho đến bây giờ, ở một số nơi tôi đã sử dụng cảm giác như hack với exec (). Về cơ bản làm những việc như:

exec("doTask.php $arg1 $arg2 $arg3 >/dev/null 2>&1 &");

Điều này có vẻ hiệu quả, nhưng tôi tự hỏi liệu có cách nào tốt hơn không. Tôi đang xem xét việc viết một hệ thống xếp hàng các tác vụ trong bảng MySQL và một tập lệnh PHP chạy dài riêng biệt truy vấn bảng đó một lần trong một giây và thực hiện bất kỳ tác vụ mới nào mà nó tìm thấy. Điều này cũng có lợi thế là cho phép tôi phân chia nhiệm vụ giữa một số máy công nhân trong tương lai nếu tôi cần.

Tôi có phát minh lại bánh xe không? Có giải pháp nào tốt hơn hack exec () hay hàng đợi MySQL không?

Câu trả lời:


80

Tôi đã sử dụng phương pháp xếp hàng và nó hoạt động tốt khi bạn có thể trì hoãn việc xử lý đó cho đến khi tải máy chủ của bạn ở chế độ chờ, cho phép bạn quản lý tải khá hiệu quả nếu bạn có thể phân vùng "các tác vụ không khẩn cấp" một cách dễ dàng.

Việc tự mình thực hiện không quá khó khăn, đây là một vài lựa chọn khác để kiểm tra:

  • GearMan - câu trả lời này đã được viết vào năm 2009, và kể từ đó GearMan có vẻ là một lựa chọn phổ biến, xem các bình luận bên dưới.
  • ActiveMQ nếu bạn muốn một hàng đợi tin nhắn mã nguồn mở đầy đủ.
  • ZeroMQ - đây là một thư viện socket khá thú vị, giúp bạn dễ dàng viết mã phân tán mà không phải lo lắng quá nhiều về chính việc lập trình socket. Bạn có thể sử dụng nó để xếp hàng tin nhắn trên một máy chủ - bạn chỉ cần ứng dụng web của mình đẩy thứ gì đó đến hàng đợi mà ứng dụng bảng điều khiển đang chạy liên tục sẽ tiêu thụ vào cơ hội phù hợp tiếp theo
  • beanstalkd - chỉ tìm thấy cái này trong khi viết câu trả lời này, nhưng trông thú vị
  • dropr là một dự án xếp hàng tin nhắn dựa trên PHP, nhưng đã không được duy trì tích cực kể từ tháng 9 năm 2010
  • php-enqueue là một trình bao bọc được duy trì gần đây (2017) xung quanh một loạt các hệ thống xếp hàng
  • Cuối cùng, một bài đăng trên blog về việc sử dụng memcached để xếp hàng tin nhắn

Một cách tiếp cận khác, có lẽ đơn giản hơn là sử dụng ign_user_abort - một khi bạn đã gửi trang cho người dùng, bạn có thể xử lý cuối cùng mà không sợ bị chấm dứt sớm, mặc dù điều này có tác dụng xuất hiện để kéo dài thời gian tải trang từ người dùng Góc nhìn cá nhân.


Cám ơn vì những mẹo hay. Một điều cụ thể về ign_user_abort không thực sự giúp ích trong trường hợp của tôi, toàn bộ mục tiêu của tôi là để tránh sự chậm trễ không cần thiết cho người dùng.
davr

2
Nếu bạn đặt tiêu đề HTTP Độ dài nội dung trong phản hồi "Cảm ơn bạn đã đăng ký", thì trình duyệt sẽ đóng kết nối sau khi nhận được số byte được chỉ định. Điều này khiến quá trình phía máy chủ chạy (giả sử rằng ign_user_abort được đặt) mà không khiến người dùng cuối phải chờ. Tất nhiên, bạn sẽ cần tính toán kích thước của nội dung phản hồi trước khi hiển thị các tiêu đề, nhưng điều đó khá dễ dàng cho các phản hồi ngắn.
Peter

1
Gearman ( gearman.org ) là một hàng đợi tin nhắn mã nguồn mở tuyệt vời là nền tảng chéo. Bạn có thể viết công nhân bằng C, PHP, Perl hoặc bất kỳ ngôn ngữ nào khác. Có các plugin UDF Gearman cho MySQL và bạn cũng có thể sử dụng Net_Gearman từ PHP hoặc trình khách lê gearman.
Justin Swanhart

Gearman sẽ là những gì tôi muốn giới thiệu hôm nay (năm 2015) trên bất kỳ hệ thống xếp hàng công việc tùy chỉnh nào.
Peter

Một tùy chọn khác là thiết lập máy chủ nút js để xử lý yêu cầu và trả về phản hồi nhanh với một tác vụ ở giữa. Nhiều thứ bên trong tập lệnh js nút được thực thi không đồng bộ, chẳng hạn như yêu cầu http.
Zordon

22

Khi bạn chỉ muốn thực hiện một hoặc một vài yêu cầu HTTP mà không phải chờ phản hồi, thì cũng có một giải pháp PHP đơn giản.

Trong tập lệnh gọi:

$socketcon = fsockopen($host, 80, $errno, $errstr, 10);
if($socketcon) {   
   $socketdata = "GET $remote_house/script.php?parameters=... HTTP 1.1\r\nHost: $host\r\nConnection: Close\r\n\r\n";      
   fwrite($socketcon, $socketdata); 
   fclose($socketcon);
}
// repeat this with different parameters as often as you like

Trên script.php, bạn có thể gọi các hàm PHP này trong các dòng đầu tiên:

ignore_user_abort(true);
set_time_limit(0);

Điều này khiến tập lệnh tiếp tục chạy mà không bị giới hạn thời gian khi kết nối HTTP bị đóng.


set_time_limit không có hiệu lực nếu php chạy ở chế độ an toàn
Baptiste Pernet

17

Một cách khác để xử lý fork là thông qua curl. Bạn có thể thiết lập các tác vụ nội bộ của mình dưới dạng dịch vụ web. Ví dụ:

Sau đó, trong tập lệnh truy cập người dùng của bạn thực hiện cuộc gọi đến dịch vụ:

$service->addTask('t1', $data); // post data to URL via curl

Dịch vụ của bạn có thể theo dõi hàng đợi các nhiệm vụ với mysql hoặc bất cứ điều gì bạn thích là: tất cả được gói gọn trong dịch vụ và tập lệnh của bạn chỉ tiêu thụ URL. Điều này giải phóng bạn để di chuyển dịch vụ sang máy / máy chủ khác nếu cần thiết (tức là dễ dàng mở rộng).

Thêm ủy quyền http hoặc chương trình ủy quyền tùy chỉnh (như dịch vụ web của Amazon) cho phép bạn mở các nhiệm vụ của mình để người khác / dịch vụ sử dụng (nếu bạn muốn) và bạn có thể đưa nó đi xa hơn và thêm dịch vụ giám sát lên trên để theo dõi hàng đợi và trạng thái nhiệm vụ.

Nó có một chút công việc thiết lập nhưng có rất nhiều lợi ích.


1
Tôi không thích cách tiếp cận này vì nó làm quá tải máy chủ web
Oved Yavine

7

Tôi đã sử dụng Beanstalkd cho một dự án và dự định thực hiện lại. Tôi đã tìm thấy nó là một cách tuyệt vời để chạy các quy trình không đồng bộ.

Một vài điều tôi đã làm với nó là:

  • Thay đổi kích thước hình ảnh - và với một hàng đợi được tải nhẹ chuyển sang tập lệnh PHP dựa trên CLI, thay đổi kích thước hình ảnh lớn (2mb +) vẫn hoạt động tốt, nhưng cố gắng thay đổi kích thước các hình ảnh tương tự trong một ví dụ mod_php thường xuyên gặp vấn đề về không gian bộ nhớ (I đã giới hạn quá trình PHP xuống còn 32 MB và việc thay đổi kích thước mất nhiều hơn thế)
  • kiểm tra trong tương lai - beanstalkd có độ trễ có sẵn cho nó (làm cho công việc này chỉ khả dụng để chạy sau X giây) - vì vậy tôi có thể loại bỏ 5 hoặc 10 kiểm tra cho một sự kiện, muộn hơn một chút

Tôi đã viết một hệ thống dựa trên Zend-Framework để giải mã url 'đẹp', ví dụ, để thay đổi kích thước hình ảnh mà nó sẽ gọi QueueTask('/image/resize/filename/example.jpg') . URL đầu tiên được giải mã thành một mảng (mô-đun, bộ điều khiển, hành động, tham số), sau đó được chuyển đổi thành JSON để tiêm vào chính hàng đợi.

Một tập lệnh cli chạy dài sau đó chọn công việc từ hàng đợi, chạy nó (thông qua Zend_Router_Simple) và nếu được yêu cầu, hãy đưa thông tin vào memcached để trang web PHP nhận theo yêu cầu khi hoàn thành.

Một nếp nhăn tôi cũng đã đưa ra là tập lệnh cli chỉ chạy trong 50 vòng trước khi khởi động lại, nhưng nếu nó muốn khởi động lại theo kế hoạch, nó sẽ thực hiện ngay lập tức (được chạy qua tập lệnh bash). Nếu có một vấn đề và tôi đã làm exit(0)(giá trị mặc định cho exit;hoặc die();) thì trước tiên nó sẽ tạm dừng trong vài giây.


Tôi thích vẻ ngoài của beanstalkd, một khi họ thêm kiên trì tôi nghĩ nó sẽ hoàn hảo.
davr

Đó là đã có trong codebase và đang ổn định. Tôi cũng mong chờ 'công việc được đặt tên', vì vậy tôi có thể ném mọi thứ vào đó, nhưng biết rằng nó sẽ không được thêm vào nếu đã có một công việc ở đó. Tốt cho các sự kiện thường xuyên.
Alister Bulman

@AlisterBulman bạn có thể cung cấp thêm thông tin hoặc ví dụ cho "Tập lệnh cli chạy dài sau đó chọn công việc từ hàng đợi". Tôi đang cố gắng xây dựng một kịch bản cli như vậy cho ứng dụng của mình.
Sasi varna kumar

7

Nếu nó chỉ là một câu hỏi về việc cung cấp các tác vụ đắt tiền, trong trường hợp php-fpm được hỗ trợ, tại sao không sử dụng fastcgi_finish_request()chức năng?

Hàm này tuôn ra tất cả dữ liệu phản hồi cho khách hàng và hoàn thành yêu cầu. Điều này cho phép thực hiện các nhiệm vụ tốn thời gian mà không để kết nối với máy khách mở.

Bạn không thực sự sử dụng tính không điển hình theo cách này:

  1. Tạo tất cả mã chính của bạn đầu tiên.
  2. Hành hình fastcgi_finish_request() .
  3. Làm tất cả những thứ nặng nề.

Một lần nữa php-fpm là cần thiết.


5

Đây là một lớp đơn giản tôi đã mã hóa cho ứng dụng web của mình. Nó cho phép bỏ các tập lệnh PHP và các tập lệnh khác. Hoạt động trên UNIX và Windows.

class BackgroundProcess {
    static function open($exec, $cwd = null) {
        if (!is_string($cwd)) {
            $cwd = @getcwd();
        }

        @chdir($cwd);

        if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
            $WshShell = new COM("WScript.Shell");
            $WshShell->CurrentDirectory = str_replace('/', '\\', $cwd);
            $WshShell->Run($exec, 0, false);
        } else {
            exec($exec . " > /dev/null 2>&1 &");
        }
    }

    static function fork($phpScript, $phpExec = null) {
        $cwd = dirname($phpScript);

        @putenv("PHP_FORCECLI=true");

        if (!is_string($phpExec) || !file_exists($phpExec)) {
            if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
                $phpExec = str_replace('/', '\\', dirname(ini_get('extension_dir'))) . '\php.exe';

                if (@file_exists($phpExec)) {
                    BackgroundProcess::open(escapeshellarg($phpExec) . " " . escapeshellarg($phpScript), $cwd);
                }
            } else {
                $phpExec = exec("which php-cli");

                if ($phpExec[0] != '/') {
                    $phpExec = exec("which php");
                }

                if ($phpExec[0] == '/') {
                    BackgroundProcess::open(escapeshellarg($phpExec) . " " . escapeshellarg($phpScript), $cwd);
                }
            }
        } else {
            if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
                $phpExec = str_replace('/', '\\', $phpExec);
            }

            BackgroundProcess::open(escapeshellarg($phpExec) . " " . escapeshellarg($phpScript), $cwd);
        }
    }
}

4

Đây là cùng một phương pháp tôi đã sử dụng trong một vài năm nay và tôi đã không thấy hoặc tìm thấy bất cứ điều gì tốt hơn. Như mọi người đã nói, PHP là một luồng đơn, do đó bạn không thể làm gì khác.

Tôi thực sự đã thêm một cấp độ nữa cho điều này và đó là nhận và lưu trữ id quá trình. Điều này cho phép tôi chuyển hướng đến một trang khác và để người dùng ngồi trên trang đó, sử dụng AJAX để kiểm tra xem quy trình đã hoàn tất chưa (id quá trình không còn tồn tại). Điều này hữu ích cho các trường hợp độ dài của tập lệnh sẽ khiến trình duyệt hết thời gian, nhưng người dùng cần đợi tập lệnh đó hoàn thành trước bước tiếp theo. (Trong trường hợp của tôi, nó đã xử lý các tệp ZIP lớn bằng CSV như các tệp có thêm tới 30 000 bản ghi vào cơ sở dữ liệu mà sau đó người dùng cần xác nhận một số thông tin.)

Tôi cũng đã sử dụng một quy trình tương tự để tạo báo cáo. Tôi không chắc chắn mình sẽ sử dụng "xử lý nền" cho một cái gì đó như email, trừ khi có vấn đề thực sự với một bản chậm. Thay vào đó, tôi có thể sử dụng bảng làm hàng đợi và sau đó có một quy trình chạy mỗi phút để gửi email trong hàng đợi. Bạn sẽ cần phải cảnh giác gửi email hai lần hoặc các vấn đề tương tự khác. Tôi cũng sẽ xem xét một quy trình xếp hàng tương tự cho các nhiệm vụ khác.


1
Phương pháp nào bạn đang đề cập đến trong câu đầu tiên của bạn?
Simon East


2

Đó là một ý tưởng tuyệt vời để sử dụng cURL theo đề xuất của rojoca.

Đây là một ví dụ. Bạn có thể theo dõi text.txt trong khi tập lệnh đang chạy ở chế độ nền:

<?php

function doCurl($begin)
{
    echo "Do curl<br />\n";
    $url = 'http://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
    $url = preg_replace('/\?.*/', '', $url);
    $url .= '?begin='.$begin;
    echo 'URL: '.$url.'<br>';
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $result = curl_exec($ch);
    echo 'Result: '.$result.'<br>';
    curl_close($ch);
}


if (empty($_GET['begin'])) {
    doCurl(1);
}
else {
    while (ob_get_level())
        ob_end_clean();
    header('Connection: close');
    ignore_user_abort();
    ob_start();
    echo 'Connection Closed';
    $size = ob_get_length();
    header("Content-Length: $size");
    ob_end_flush();
    flush();

    $begin = $_GET['begin'];
    $fp = fopen("text.txt", "w");
    fprintf($fp, "begin: %d\n", $begin);
    for ($i = 0; $i < 15; $i++) {
        sleep(1);
        fprintf($fp, "i: %d\n", $i);
    }
    fclose($fp);
    if ($begin < 10)
        doCurl($begin + 1);
}

?>

2
Nó thực sự có ích nếu mã nguồn sẽ được bình luận. Tôi không biết những gì đang diễn ra trong đó và những phần nào là ví dụ và những phần nào có thể tái sử dụng cho mục đích riêng của tôi.
Thomas Tempelmann

1

Thật không may, PHP không có bất kỳ loại khả năng phân luồng riêng nào. Vì vậy, tôi nghĩ rằng trong trường hợp này, bạn không có lựa chọn nào khác ngoài việc sử dụng một số loại mã tùy chỉnh để làm những gì bạn muốn làm.

Nếu bạn tìm kiếm trên mạng các công cụ phân luồng PHP, một số người đã nghĩ ra các cách để mô phỏng các luồng trên PHP.


1

Nếu bạn đặt tiêu đề HTTP Độ dài nội dung trong phản hồi "Cảm ơn bạn đã đăng ký", thì trình duyệt sẽ đóng kết nối sau khi nhận được số byte được chỉ định. Điều này làm cho quá trình phía máy chủ chạy (giả sử rằng ign_user_abort được đặt) để nó có thể hoàn thành hoạt động mà không khiến người dùng cuối phải chờ đợi.

Tất nhiên, bạn sẽ cần tính kích thước của nội dung phản hồi trước khi hiển thị các tiêu đề, nhưng điều đó khá dễ dàng đối với các phản hồi ngắn (ghi đầu ra vào chuỗi, gọi strlen (), tiêu đề cuộc gọi (), kết xuất chuỗi).

Cách tiếp cận này có ưu điểm là không buộc bạn phải quản lý hàng đợi "mặt trước" và mặc dù bạn có thể cần thực hiện một số công việc ở mặt sau để ngăn các quá trình con HTTP chạy đua với nhau, đó là điều bạn cần phải làm , dù sao.


Điều này dường như không hoạt động. Khi tôi sử dụng header('Content-Length: 3'); echo '1234'; sleep(5);thì mặc dù trình duyệt chỉ mất 3 ký tự, nó vẫn đợi trong 5 giây trước khi hiển thị phản hồi. Tôi đang thiếu gì?
Thomas Tempelmann

@ThomasTempelmann - Có lẽ bạn cần gọi flush () để buộc đầu ra thực sự được hiển thị ngay lập tức, nếu không đầu ra sẽ được đệm cho đến khi tập lệnh của bạn thoát hoặc đủ dữ liệu được gửi đến STDOUT để xóa bộ đệm.
Peter

Tôi đã thử nhiều cách để xả, tìm thấy ở đây trên SO. Không có ai giúp đỡ. Và dữ liệu dường như cũng được gửi không được nén, như người ta có thể biết phpinfo(). Điều khác duy nhất tôi có thể tưởng tượng là tôi cần đạt kích thước bộ đệm tối thiểu trước tiên, ví dụ 256 hoặc hơn byte.
Thomas Tempelmann

@ThomasTempelmann - Tôi không thấy bất cứ điều gì trong câu hỏi của bạn hoặc câu trả lời của tôi về gzip (thường có ý nghĩa để kịch bản đơn giản nhất hoạt động trước khi thêm các lớp phức tạp). Để thiết lập khi máy chủ thực sự gửi dữ liệu, bạn có thể sử dụng gói sniffer của plugin trình duyệt (như fiddler, tamperdata, v.v.). Sau đó, nếu bạn thấy rằng máy chủ web thực sự giữ tất cả đầu ra tập lệnh cho đến khi thoát bất kể việc xả, thì bạn cần sửa đổi cấu hình máy chủ web của mình (không có gì mà tập lệnh PHP của bạn có thể làm trong trường hợp đó).
Peter

Tôi sử dụng một dịch vụ web ảo, vì vậy tôi có ít quyền kiểm soát cấu hình của nó. Tôi đã hy vọng tìm thấy những gợi ý khác về những gì có thể là thủ phạm, nhưng có vẻ như câu trả lời của bạn đơn giản là không thể áp dụng phổ biến như nó xuất hiện. Quá nhiều thứ có thể đi sai, rõ ràng. Giải pháp của bạn chắc chắn dễ thực hiện hơn nhiều so với tất cả các anwers khác được đưa ra ở đây. Quá tệ, nó không làm việc cho tôi.
Thomas Tempelmann

1

Nếu bạn không muốn ActiveMQ toàn diện, tôi khuyên bạn nên xem xét RabbitMQ . RabbitMQ là tin nhắn nhẹ sử dụng tiêu chuẩn AMQP .

Tôi cũng khuyên bạn nên xem xét php-amqplib - một thư viện khách AMQP phổ biến để truy cập các nhà môi giới tin nhắn dựa trên AMQP.


0

Tôi nghĩ bạn nên thử kỹ thuật này, nó sẽ giúp gọi bao nhiêu trang bạn thích, tất cả các trang sẽ chạy cùng một lúc một cách độc lập mà không phải chờ mỗi phản hồi của trang là không đồng bộ.

cornjobpage.php // trang chính

    <?php

post_async("http://localhost/projectname/testpage.php", "Keywordname=testValue");
//post_async("http://localhost/projectname/testpage.php", "Keywordname=testValue2");
//post_async("http://localhost/projectname/otherpage.php", "Keywordname=anyValue");
//call as many as pages you like all pages will run at once independently without waiting for each page response as asynchronous.
            ?>
            <?php

            /*
             * Executes a PHP page asynchronously so the current page does not have to wait for it to     finish running.
             *  
             */
            function post_async($url,$params)
            {

                $post_string = $params;

                $parts=parse_url($url);

                $fp = fsockopen($parts['host'],
                    isset($parts['port'])?$parts['port']:80,
                    $errno, $errstr, 30);

                $out = "GET ".$parts['path']."?$post_string"." HTTP/1.1\r\n";//you can use POST instead of GET if you like
                $out.= "Host: ".$parts['host']."\r\n";
                $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
                $out.= "Content-Length: ".strlen($post_string)."\r\n";
                $out.= "Connection: Close\r\n\r\n";
                fwrite($fp, $out);
                fclose($fp);
            }
            ?>

testpage.php

    <?
    echo $_REQUEST["Keywordname"];//case1 Output > testValue
    ?>

PS: nếu bạn muốn gửi tham số url dưới dạng vòng lặp thì hãy làm theo câu trả lời sau: https://stackoverflow.com/a/41225209/6295712


0

Sinh ra các quy trình mới trên máy chủ bằng cách sử dụng exec()hoặc trực tiếp trên một máy chủ khác bằng cách sử dụng curl hoàn toàn không có quy mô, nếu chúng tôi thực hiện, về cơ bản, bạn đang lấp đầy máy chủ của mình bằng các quy trình chạy dài có thể được xử lý bởi các máy chủ không phải web khác, và sử dụng curl liên kết với một máy chủ khác trừ khi bạn xây dựng một số loại cân bằng tải.

Tôi đã sử dụng Gearman trong một vài tình huống và tôi thấy nó tốt hơn cho trường hợp sử dụng này. Tôi có thể sử dụng một máy chủ hàng đợi công việc duy nhất để xử lý hàng đợi tất cả các công việc cần thực hiện bởi máy chủ và quay các máy chủ worker, mỗi máy chủ có thể chạy bao nhiêu phiên bản của process worker khi cần và tăng số lượng máy chủ worker khi cần và quay chúng xuống khi không cần thiết. Nó cũng cho phép tôi tắt các quy trình công nhân hoàn toàn khi cần thiết và xếp hàng các công việc cho đến khi các công nhân trở lại trực tuyến.


-4

PHP là một ngôn ngữ đơn luồng, vì vậy không có cách chính thức nào để bắt đầu một quy trình không đồng bộ với nó ngoài việc sử dụng exechoặc popen. Có một bài viết về điều đó ở đây . Ý tưởng của bạn cho một hàng đợi trong MySQL là một ý tưởng tốt.

Yêu cầu cụ thể của bạn ở đây là gửi email cho người dùng. Tôi tò mò về lý do tại sao bạn đang cố gắng thực hiện điều đó một cách không đồng bộ vì việc gửi email là một nhiệm vụ khá nhỏ và nhanh chóng để thực hiện. Tôi cho rằng nếu bạn đang gửi hàng tấn email và ISP của bạn đang chặn bạn vì nghi ngờ spam, đó có thể là một lý do để xếp hàng, nhưng ngoài lý do đó tôi không thể nghĩ ra bất kỳ lý do nào để làm theo cách này.


Email chỉ là một ví dụ, vì các nhiệm vụ khác phức tạp hơn để giải thích và nó không thực sự là vấn đề. Cách chúng tôi sử dụng để gửi email, lệnh email sẽ không trở lại cho đến khi máy chủ từ xa chấp nhận thư. Chúng tôi thấy rằng một số máy chủ thư được định cấu hình để thêm độ trễ dài (như độ trễ 10-20 giây) trước khi chấp nhận thư (có thể để chống lại spam bots) và những độ trễ này sẽ được chuyển đến người dùng của chúng tôi. Bây giờ, chúng tôi đang sử dụng một máy chủ thư cục bộ để xếp hàng các thư được gửi, vì vậy ứng dụng này không được áp dụng, nhưng chúng tôi có các nhiệm vụ khác có tính chất tương tự.
davr

Ví dụ: gửi email thông qua Google Apps Smtp với ssl và cổng 465 mất nhiều thời gian hơn bình thường.
Gixty 6/07/2015
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.