views:

131

answers:

6

Hi all,

We're currently looking into doing some performance tweaking on a website which relies heavily on a Soap webservice. But ... our servers are located in Belgium and the webservice we connect to is locate in San Francisco so it's a long distance connection to say the least.

Our website is PHP powered, using PHP's built in SoapClient class. On average a call to the webservice takes 0.7 seconds and we are doing about 3-5 requests per page. All possible request/response caching is already implemented so we are now looking at other ways to improved the connection speed.

This is the code which instantiates the SoapClient, what i'm looking for now is other ways/methods to improve speed on single requestes. Anyone has idea's or suggestions?

private function _createClient()
{
    try {

        $wsdl = sprintf($this->config->wsUrl.'?wsdl', $this->wsdl);
        $client = new SoapClient($wsdl, array(
            'soap_version'       => SOAP_1_1,
            'encoding'           => 'utf-8',
            'connection_timeout' => 5,
            'cache_wsdl'         => 1,
            'trace'              => 1,
            'features'           => SOAP_SINGLE_ELEMENT_ARRAYS
        ));

        $header_tags = array('username' => new SOAPVar($this->config->wsUsername, XSD_STRING, null, null, null, $this->ns),
                             'password' => new SOAPVar(md5($this->config->wsPassword), XSD_STRING, null, null, null, $this->ns));
        $header_body = new SOAPVar($header_tags, SOAP_ENC_OBJECT);
        $header = new SOAPHeader($this->ns, 'AuthHeaderElement', $header_body);

        $client->__setSoapHeaders($header);

    } catch (SoapFault $e){
        controller('Error')->error($id.': Webservice connection error '.$e->getCode());
        exit;
    }

    $this->client = $client;
    return $this->client;
}
+3  A: 

PHP.INI

output_buffering = On
output_handler = ob_gzhandler
zlib.output_compression = Off
Brant
Thanks! seems like an obvious one and will check but i'm looking for a rather practical approach instead of tweaking php settings which by the way are already set like you suggested :) Thanks for the suggestion tho!
ChrisR
Actually, zlib.output_compression is preferred over ob_gzhandler.
Robbie Groenewoudt
@ChrisRamakers - I use soap for internal applications. One of the features I added was to send a format param which allows me to get a json formatted data set in one node. I retrieve the data and then allow the client to set the data. This has helped because the length of the body response is less because <tag>...</tag> times 200 has been replaced with <json>{....}</json>
Brant
+3  A: 

So, the root problem is number of request you have to do. What about creating grouped services ?

  • If you are in charge of the webservices, you could create specialized webservices which do multiple operations at the same time so your main app can just do one request per page.
  • If not you can relocate your app server near SF.
  • If relocating all the server is not possible and you can not create new specialized webservices, you could add a bridge, located near the webservices server. This bridge would provide the specialized webservices and be in charge of calling the atomic webservices. Instead of 0.7s * 5 you'd have 0.7s + 5 * 0.1 for example.
Arkh
+1 for the brigde, i'm not in charge of the WS itself but a bridge might be a valid solution!
ChrisR
+1  A: 

1 You can assert your soap server use gzip compression for http content, as well as your site output does. A 0,7s roundup to SF seems a bit long, it's either webservice is long to answer, either there is an important natwork latency. If you can, give a try to other hosting companies for your belgium server, in France some got a far better connectivity to the US than others. I experienced to move a website from one host o another and network latency between Paris and New york has almost doubled ! it's uge and my client with a lot of US visitors was unhappy with it. The solution of relocating web server to SF can be an option, you'll get a far better connectivity between servers, but be careful of latency if your visitors are mainly located in Europe.

2 You can use an opcode cache mecanism, such as xcache or APC. It wil not change the soap latency, but will improve php execution time.

3 Depending if soap request are repetitive, and how long could a content update could be extended, you can give it a real improvement using cache on soap results. I suggest you to use in-memory caching system (Like xcache/memcached or other) because they're ay much faster than file or DB cache system.

From your class, the createclient method isn't the most adapted exemple functionality to be cached, but for any read operation it's just the best way to perf :

private function _createClient()
{
  $xcache_key = 'clientcache'
  if (!xcache_isset($key)) {
      $ttl = 3600; //one hour cache lifetime
      $client = $this->_getClient(); ///private method embedding your soap request          
      xcache_set($xcache_key, $client, $ttl);
      return $client;
   }
   //return result form mem cache
   return xcache_get($xcache_key);
}

The example is for xcache extension, but you can use other systems in a very similar manner

4 To go further you can use similar mecanism to cache your php processing results (like template rendering output and other ressource consumming operations). The key to success with this technic is to know exactly wich part is cached and for how long it will stay withous refreshing.

Benoit
We've recently implemented a caching mechanism that depends on the last update time of our records in the WS. And clientside caching is also in place already. I'm not saying we've pushed everything to the max but the gains would be negligible when compared to over 5 requests that take .5s across. Geographically redistributing the servers might work too but all our visitors/users are from belgium and the netherlands so moving our server to the US introduced general latency all over the website.
ChrisR
ok, it seems the only option to evaluate is WS server optimization or better relocation to belgium. The best performing SOA I've seen were hosted in the same place, same rack, but I aknowledge the solution has this architecture from the start
Benoit
+2  A: 

Do you know for sure that it is the network latency slowing down each request? 0.7s seems a long round time, as Benoit says. I'd look at doing some benchmarking - you can do this with curl, although I'm not sure how this would work with your soap client.

Something like:

$ch = curl_init('http://path/to/sanfrancisco/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
$info = curl_getinfo($ch);

$info will return an array including elements for total_time, namelookup_time, connect_time, pretransfer_time, starttransfer_time and redirect_time. From these you should be able to work out whether it's the dns, request, the actual soap server or the response that's taking up the time.

One obvious thing that's just occurred to me is are you requesting the SOAP server via a domain or an IP? If you're using a domain, your dns might be slowing things down significantly (although it will be cached at several stages). Check your local dns time (in your soap client or php.ini - not sure) and the TTL of your domain (in your DNS Zone). Set up a static IP for your SanFran server and reference it that way if not already.

adam
The roundtrip is indeed 0.7 - 0.5 s ... it's not a simple network command like ping but there also happens some processing on the server that usually takes some time if not able to fetch from cache.
ChrisR
Yeah - I wasn't suggesting a ping. Break down the 0.7s - including a bit of benchmarking of the actual app.
adam
@Chris if a ping to the WS server is fast the distance is (most likely) _not_ your problem :)
Rune FS
+1  A: 

Optimize the Servers (not the client!) HTTP responce by using caching and HTTP compressing. Check out the hits at yahoo http://developer.yahoo.com/performance/rules.html

powtac
A: 

Any chance of using an AJAX interface.. if the requests can be happening in the background, you will not seem to be left waiting for the response.

Bingy