1

使用 perl、wsdl 和多线程的 Web 服务不起作用:

  1. 使用线程执行命令行:有效
  2. 带有线程的肥皂客户端调用:不起作用
  3. 没有线程的肥皂客户端调用:有效

在这里,我尝试使用线程更新数千个筛子文件,但如果我使用线程,它不起作用。我正在尝试使用 perl 快速制作 web 服务,目前它是用 php 编写的,但是使用 web 服务的线程不起作用任何帮助都会有所帮助。

当我从肥皂客户端(soap_client.pl)调用 Web 服务时,它返回以下错误。

500 Server closed connection without sending any data back

安装的 perl 模块:

MIME::Parser
SOAP::Lite

阿帕奇模块:

mod_perl

阿帕奇虚拟主机:

<VirtualHost 192.168.1.187:80>
 ServerName sieve.net
 ServerAlias www.sieve.net
 DocumentRoot /web/sieve.net/htdocs
 ErrorLog /var/log/httpd/sieve.net_error_log
 TransferLog /var/log/httpd/sieve.net_access_log

 <Directory "/web/sieve.net/htdocs">
        <FilesMatch "\.mhtml$|\.pl$|\.html$">
                Options         +ExecCGI
                AddHandler      cgi-script .cgi .pl .html
                SetHandler      perl-script
                PerlHandler     ModPerl::Registry
                PerlSendHeader  On
        </FilesMatch>
      </Directory>
 DirectoryIndex index.phtml index.htm index.html index.pl
</VirtualHost>

sievefilter_thread.pl

#!/usr/bin/perl
use strict;
use SOAP::Lite;
use SOAP::Transport::HTTP;
use lib "/web/sieve.net/htdocs";
use Sieve;
use threads;
use Thread::Queue;

my $soap = SOAP::Transport::HTTP::CGI->new(
    dispatch_to => 'manageSieve'
);
$soap->handle();

package manageSieve;
sub updateSieveFilter {
    my ($package, $client_id) = @_;
    my @users = ({
                    'Password' => 'test',
                'Login' => 'test1@example.in'
                 },
             {
                    'Password' => 'test',
                'Login' => 'test2@example.in'
                 },
             {
                    'Password' => 'test',
                'Login' => 'test3@example.in'
                 },
             {
                    'Password' => 'test',
                'Login' => 'test4@example.in'
                 },         
             {
                    'Password' => 'test',
                'Login' => 'test5@example.in'
                 }, 
        );
    if(@users) {
        my $THREADS = 30;
                my $Qwork = new Thread::Queue;
                my $Qresults = new Thread::Queue;

                # If i return any value from here it wokrs. 
                ## Create the pool of workers
                my @pool = map{
                        threads->create( \&updateClientUsersSieve, $Qwork, $Qresults )
                } 1 .. $THREADS;

                # Does not return any value from here.

                foreach my $user (@users){
                        $Qwork->enqueue( $user );
                        if( $counter % 100 == 0){
                                sleep 1;
                        }
                        $counter++;
                }
                $Qwork->enqueue( (undef) x $THREADS );
        ## Process the results as they become available
                for ( 1 .. $THREADS ) {
                        while( $result = $Qresults->dequeue ) {
                                #print $result;
                        }
                }
                # Clean up the threads          
                $_->join for @pool;
                return 1;
        }
        return 0;   
}

sub updateClientUsersSieve {
        my $tid = threads->tid;
        my $result = 1;
        my( $Qwork, $Qresults ) = @_;
        my ($login, $password);
        while( my $user = $Qwork->dequeue ) {
                ($login, $password) = ($user->{'Login'}, $user->{'Password'});

                my $sieveObj    = new Sieve($login, $password);
                $result   = $sieveObj->sieveLogin();
                $Qresults->enqueue( $result );
        }
        $Qresults->enqueue( undef ); ## Signal this thread is finished
}
1;

筛分.pm

#!/usr/bin/perl
package Sieve;
use Net::ManageSieve;
use strict;

sub new {
   my $class = shift;
   my $self = {
        _username => shift,
        _password => shift,
        _sieve    => undef,
   };
   bless $self, $class;
   return $self;
}

sub sieveLogin {
    my ($self)  = @_;
    my $sieveServer     = 'localhost';
    my $sievePort       = 2000;
    my $authType        = 'PLAIN';
    my $username        = $self->{_username};
    my $password        = $self->{_password};
    my $capabilities    = "require [";
    my $activescript    = "";
    my $script_name     = "sievephp_testscript";
    my $error           = undef;

    $self->{_sieve}  = Net::ManageSieve->new("$sieveServer:$sievePort");
    if(!$self->{_sieve}->login($username, $password)){
    return 0;
    }

    $capabilities = $self->{_sieve}->capabilities->{sieve};
    $capabilities =~ s/\s/\",\"/g;
    $capabilities = 'require ["'.$capabilities.'"];'."\n";
    $activescript = $capabilities;
    $activescript .= "\n";
    $activescript .= "if allof (size :over 1000K ){ reject text: Your mail Has been rejected due to mailsize control\n\n.;";
    $activescript .= "stop;}";

    $self->{_sieve}->putscript($script_name, $activescript);
    $self->{_sieve}->logout; 
    return 1;       
}
1;

筛子.wsdl

<?xml version="1.0"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="urn:manageSieve" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="HelloService" targetNamespace="urn:manageSieve" xmlns:y="urn:manageSieve">
<message name="updateSieveFilterRequest">
    <part name="client_code" type="xsd:string"/>
</message>
<message name="updateSieveFilterResponse">
    <part name="Result" type="xsd:string"/>
</message>
<portType name="Hello_PortType">
    <operation name="updateSieveFilter">
        <input message="tns:updateSieveFilterRequest"/>
        <output message="tns:updateSieveFilterResponse"/>
    </operation>
</portType>
<binding name="Hello_Binding" type="tns:Hello_PortType">
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="updateSieveFilter">
        <soap:operation soapAction="urn:manageSieve#updateSieveFilter"/>
        <input>
        <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:manageSieve" use="encoded"/>
        </input>
        <output>
        <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:manageSieve" use="encoded"/>
        </output>
    </operation>
</binding>
<service name="Hello_Service">
<documentation>WSDL File for HelloService</documentation>
<port binding="tns:Hello_Binding" name="Hello_Port">
    <soap:address location="http://sieve.net/sievefilter_thread.pl"/>
</port>
</service>
</definitions>

肥皂客户端.pl

use SOAP::Lite;
my $client = SOAP::Lite->service("http://sieve.net/sieve.wsdl");
my $result = $client->updateSieveFilter(17);
print $result;
4

1 回答 1

0

我对你的线程代码有点困惑。您必须在创建线程之前将工作传递到队列中,并在它们完成后处理它们。

$Qresults->enqueue(undef); ## 表明这个线程已经完成<--这不是必需的

          foreach my $user (@users){
                    $Qwork->enqueue( $user );
                    if( $counter % 100 == 0){
                            sleep 1;
                    }
                    $counter++;
          }
           $Qwork->enqueue( (undef) x $THREADS );

            ## Create the pool of workers
            my @pool = map{
                    threads->create( \&updateClientUsersSieve, $Qwork, $Qresults )
            } 1 .. $THREADS;             
            # Clean up the threads          
            $_->join for @pool;
            ## Process the results as they become available
            while( $result = $Qresults->dequeue ) {
               print $result;
            }

            return 1;
于 2013-03-05T13:03:49.093 回答