1

perl、wsdl、およびマルチスレッドを使用する Web サービスが機能しない:

  1. スレッドを使用したコマンドライン実行: 動作
  2. スレッドを使用した SOAP クライアント呼び出し: 機能しません
  3. スレッド化なしの SOAP クライアント呼び出し: 動作

ここで、スレッドを使用して何千ものふるいファイルを更新しようとしていますが、スレッドを使用すると機能しません。Perl を使用して Web サービスを高速化しようとしていますが、現在は php で記述されていますが、Web サービスを使用したスレッド化が役に立ちません。

SOAP クライアント (soap_client.pl) から Web サービスを呼び出すと、次のエラーが返されます。

500 Server closed connection without sending any data back

インストールされた perl モジュール:

MIME::Parser
SOAP::Lite

アパッチ モジュール:

mod_perl

Apache 仮想ホスティング:

<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;

sieve.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>

soap_client.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 に答える