API Proxy timeout

My client is an Apigee Cloud customer and we have an issue with timeouts.

As per the documentation here,

Cloud customers, who can't modify the Edge timeouts, can also configure an API proxy timeout, as long as the timeout is shorter than the standard Edge message processor timeout of 57 seconds.

Our backend application sometimes takes as much as 300 seconds to respond back. So when this happens, while the message processor is perfectly ok with waiting for the backend to respond (io.timeout.millis, connect.timeout.millis and keepalive.timeout.millis set to appropriate values), the router responds back with a 504 Gateway Timeout error in HTML

	<!DOCTYPE html>
<html>
    <head>
        <title>Error</title>
        <style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
    </head>
    <body>
        <h1>An error occurred.</h1>
        <p>Sorry, the page you are looking for is currently unavailable.
            <br/>
Please try again later.
        </p>
    </body>
</html>
	

So how do I ensure that my client does not get this error back for a transction that takes longer than 57 seconds?

0 11 6,792
11 REPLIES 11

Not applicable

You can override timeout of an api proxy by using api.timeout property. The same document posted above describes this property (credits to @Maruti Chand). However, a slow API is a sign of an underlying system that might require a different API design pattern to avoid hurting the user experience.

So, without knowing too much about your use case, I'd suggest considering implementing a Batch Operation API Design Pattern. In this pattern, your API kicks a job in the background and immediately returns an id, which can be used to poll the status of the long-running job. Once the job finishes, the status of the job will transition to complete. A good example of this approach is done by MailChimp Batch Operations API.

If this is a machine-to-machine type of API, you can leverage more sophisticated event-driven patterns such as PubSub(e.g. GCP Cloud PubSub) to publish the change of the status of your job via APIs and avoid any type of long-polling.

I appreciate your comment.

as long as the timeout is shorter than the standard Edge message processor timeout of 57 seconds.

Our issue is precisely this: the api.timeout property is overridden if it is set to anything over 57 seconds. It is only useful if the timeout is to be set to a value less than 57 sec. We want to see if there is any way to receive responses that take longer than 57 seconds.

For now, we are implementing a pilot program with some other objectives in mind - and so we cannot implement any Batch or Pub-sub models at present. These real-time transactions have to handled as such.

However, thanks for the ideas. Maybe i this issue cannot be rectified in any other manner, we might have to change the underlying transaction model.

Thanks for the answer!

Edit

PS: I still find it a little strange that the cloud solution cannot handle any transaction that takes longer than 57 sec. Surely we are missing something?

Makes sense. I hadn't been able to workaround it. Let's check if others did.

@maruthi, any idea if other changes are required? Or definitely, there's no workaround.

@Diego Zuluaga This property works fine in private cloud and am not sure why it was restricted to < 57 sec as there is no value of that property if you are going to set your io.timeout >= 57 sec.

@Stephen Gilson, Any reason why this restriction on NB side and if this is for a reason, we should put a note on the io.timeout usage.

@Maruti Chand By default the Router has a timeout of 57s to read from MP, and MP has a default timeout of 55s reading from target. So when MP fails from target at 55s, the Router still has a chance to respond proper errors before it times out at 57s.

From the doc, it looks like you can work with Apigee Support to discuss lengthening the Router timeout, but I do not know what the restrictions are.

Stephen

Well, I don't want the timeouts on the router as I want the timeout just for one API-proxy and I believe that's the whole intention of that property.

@arghya das, any thoughts?

same error. is there a solution for this in API proxy level?

Have you tried following property in your TargetEndpoint ?

<Properties><Property name="io.timeout.millis">180000</Property> </Properties>.

This should work on API proxy level. 180 is an example btw.

I recently had a discussion about the same issue with the Apigee support and what they suggested is to change the proxy_read_timeout setting on the virtual host.

You can do this by 2 ways:

  1. From the Edge UI, navigate to Admin - Virtual Hosts section, change this setting in a particular vHost.

    9893-screenshot-2020-05-14-at-14201-pm.png

  2. You can use the Apigee update virtual host management API for this purpose as well:
    https://apidocs.apigee.com/management/apis/put/organizations/%7Borg_name%7D/environments/%7Benv_name...

Note:

  1. The proxy_read_timeout value should be greater than the io.timeout.millis. This ensure proxy will timeout only when the wait time for target to respond is over.
  2. Once you update a vHost, it will impact all the proxies in that environment. It means, the proxy read timeout will be applied to those proxies as well that don't need it.

This is what have helped me but I also noticed one thing: proxy doesn't timeout exactly as per the value in the proxy read timeout. It usually takes more time.

Having said that, I would like other people's comments on this topic as well.

thanks

Hi @Mohammad

Thank you for the information. But is there a way where we don't have to update the timeout of the virtual host? Is there a way where in we can adjust timeout inside the API Proxy?

Thanks

I think we can mention the same property in the proxy endpoint section but I am not sure if that actually changes the setting at the vHost for that particular proxy.