Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

client getting timeout when monitoring items. Is there a way to set the RequestHeader? #141

Closed
pelis opened this issue Nov 30, 2015 · 18 comments
Labels

Comments

@pelis
Copy link
Sponsor

pelis commented Nov 30, 2015

Hi,
great package!
I am having trouble with client time-outs. Currently I am testing against the OPC Boiler sample server. Just to test the time-out behavior I am testing the server when it does NOT send anything - some servers the we are trying to link to will not send data for quite a while...
This is how I connect:

var options = {
    requestedPublishingInterval: 1000,  
    requestedMaxKeepAliveCount: 2,
    requestedLifetimeCount: 100, 
    maxNotificationsPerPublish: 10, 
    publishingEnabled: true, 
    priority: 10,
 }

 var subscription = new opcua.ClientSubscription(opcSession, options);
 log.info("new subscription instance created");
 subscription.on("started", function () {
     console.log ("subscription started…");
 });

subscription.on("keepalive", function () {
      lastIsAlive = (new Date()).getTime();
      console.log ("keepalive…");
});

I was hoping that the timeout would compute to:
requestedLifetimeCount * requestedPublishingInterval (1000 * 100);
No matter what values I set here, the time-out described below never changes
(“Timeout … waiting for response for” in ../lib/client/client_secure_channel_layer.js)

What I observe is:

  • I cannot influence the time-out – RequestHeader. timeoutHint is always 10000 (if this is the timeout value)
  • I cannot register to any event where I could intercept this error (I can only register on socket level when the physical connection breaks).
  • When I get the time-out, sometimes keep-alive is still intact and I will get notified on monitored items “changed” event. Unfortunately, some-times (no code change) ‘keep-alive’ seems to break as well, in which case I need to destroy the connection and re-create it again.

I have two questions:
Can I somehow increase RequestHeader.timeoutHint, or is there any way to increase the time-out?

Is there a way to intercept that event (lib/client/client_secure_channel_layer.js) ?

Thanks in advance
opcclient_timeout

@erossignon
Copy link
Member

Could you let me know where to find the "OPC Boiler sample server."
What version of node-opcua are you using ?

@pelis
Copy link
Sponsor Author

pelis commented Dec 2, 2015

I am using version 0.0.49
The sample server and client can be downloaded from the opc foundation:
https://opcfoundation.org/developer-tools/developer-kits-unified-architecture/sample-applications
(you need to be registerd for the download)
It's a bit 'odd' to start the simulation from the client, I have added a screen-shot
startsimulation

@pelis
Copy link
Sponsor Author

pelis commented Dec 2, 2015

One more little detail:
I have also tried to use clientSubscription.isActive().
I observe that once clientSubscription is created, .isActive() always returns true, even when the physical socket connection has broken (maybe isActive() is ment to reflect that the client instance object is intact)

@erossignon erossignon added the bug label Dec 2, 2015
@erossignon erossignon added this to the next version (v0.050) ? milestone Dec 2, 2015
@erossignon
Copy link
Member

Thank you I can reproduce the error.
changing options to:

var options = {
    requestedPublishingInterval: 1000,   //<< 
    requestedMaxKeepAliveCount: 5,   // <<
    requestedLifetimeCount: 10, 
    maxNotificationsPerPublish: 10,  
    publishingEnabled: true, 
    priority: 10,
 }

will cause keep alive to be send by server every = 5s = 5x1000 ms (PublishingInterval*MaxKeepAliveCount )

Note that the server may revise the various parameters:

  console.log("revised publishingInterval :", subscription.publishingInterval);
  console.log("revised lifetimeCount      :", the_subscription.lifetimeCount);
  console.log("revised maxKeepAliveCount  :", the_subscription.maxKeepAliveCount);

The PublishRequest.RequestHeader.timeoutHint shall be set to at least revisedLifetimeCount * revisedPublishingInterval or to 0, to mean infinite timeout.

erossignon added a commit that referenced this issue Dec 2, 2015
erossignon added a commit that referenced this issue Dec 2, 2015
@pelis
Copy link
Sponsor Author

pelis commented Dec 3, 2015

Wow, thanks for your quick response and your effort!
looking forward to get the new release once it is available on git

@pelis
Copy link
Sponsor Author

pelis commented Dec 3, 2015

One more suggestion:
It would be nice to get the timeout event instead of printing it to the console, I have modified client_secure_channel_layer.js (a bit dirty, have not registered the event properly):
ClientSecureChannelLayer.prototype._performMessageTransaction = function (msgType, requestMessage, callback) {
...

timerId = setTimeout(function () {
   // console.log(" Timeout .... waiting for response for ", requestMessage.requestHeader.toString());
    modified_callback(new Error("Transaction has timed out"));
   // PL code:
    self.emit("timeout", requestMessage.requestHeader);
}, timeout);

@erossignon erossignon modified the milestones: next version v0.0.51, next version (v0.050) ? Dec 3, 2015
@erossignon
Copy link
Member

@pelis, let me know if the previous commit solve your issue.

erossignon added a commit that referenced this issue Dec 12, 2015
@pelis
Copy link
Sponsor Author

pelis commented Dec 14, 2015

Yes, thanks again...
I still have various timeouts in my code to double check the connection condition.
Once we go live in a production environment (currently still in test mode) I will let you know how things turn out.
Cheers - Peter

@pelis
Copy link
Sponsor Author

pelis commented Dec 16, 2015

I have now done some more testing with various keepAliveCount variations. The problem comes back for some reason, when I increase keepAliveCount (e.g. 20).

Is there a reason why you wouldn't use requestedLifetimeCount:
var timeoutHint = self.lifetimeCount * self.publishingInterval;

@erossignon
Copy link
Member

@pelis can you describe the configuration you have that generates this problem ?

  • which OS ? what CPU ? Server side ? - Client ? - Connection ? network reliability ? number of variable to monitor etc....

Ideally I would like to recreate the situation into a end_2_end automated test that clearly demonstrate the issue. Your help is welcome.

@pelis
Copy link
Sponsor Author

pelis commented Jan 5, 2016

I am running both - server and client on a Windows 8.1 machine, using the Boiler sample above.
Not sure which combination of keepAliveCount and publishingInterval generates the timeout - just from experimenting I found the keepAliveCount = 20 and publishingInterval = 1000 causes the problem in my setup.

I have extracted the code which could be used to play or test with it - however I have not really looked into your end-2-end testing setup.
The code I have extracetd also contains my current "reconnect" implementation (#144)
How could I best provide the code (2 .js files) - in case you are interested?

@erossignon
Copy link
Member

you could publish the file in a gist => https://gist.github.com/ and reference the gist link in this thread.

@erossignon
Copy link
Member

Is there a reason why you wouldn't use requestedLifetimeCount:
var timeoutHint = self.lifetimeCount * self.publishingInterval;

Specification Part 3

OPCUA specify that the server shall send a empty Publish Response  ( as a keep-alive Message ) 
when the publishing timer has expired 'maxKeepAlive' number of times without requiring any 
NotificationMessage to be sent.

Therefore setting timeoutHint to something like (self.maxKeepAliveCount + 10 ) * self.publishingInterval shall be sufficient.

However, to deal with network latency, OPCUA suggests that the client send a bunch of PublishRequest in advance to the server.

Spec 1.02 part 4 5.13.5 Publish
[..] in high latency networks, the Client may wish to pipeline Publish requests
to ensure cyclic reporting from the Server. Pipelining involves sending more than one Publish
request for each Subscription before receiving a response. For example, if the network introduces a
delay between the Client and the Server of 5 seconds and the publishing interval for a Subscription
is one second, then the Client will have to issue Publish requests every second instead of waiting for
a response to be received before sending the next request.

This mean that the timeoutHint must be mitigated to take into account the number of unprocessed PublishRequest that are waiting in the server publish engine queue.

Knowing that the server will process then at worst every maxKeepAliveCount *publishInterval,
the timeoutHint of a publish request can be estimated to:

maxKeepAliveCount *publishInterval * nbUnprocessedPublishRequestInServerQueue.

Let me fix this.

@pelis
Copy link
Sponsor Author

pelis commented Jan 6, 2016

OK, after messing things up trying to directly upload files :-) I have now put the files in:
https://gist.github.com/pelis/b9e15b8e21bd6a84d9e6

monitor.js is not using any of the helper function - I have just used the very high-level API calls.

@erossignon
Copy link
Member

@pelis, I have been reviewing your code, and it appears to me that the reconnection strategy shall be encapsulated inside the node-opcua OPCUAClient class and not in your code. This will hide all the plumbing from you and make you code easier to manage. I suggest that we keep this issue to deal with the original topic (timeout in monitored item ) and create a new enhancement request.

@erossignon
Copy link
Member

Oops, I am confused , we will use #144 for this.

@pelis
Copy link
Sponsor Author

pelis commented Jan 7, 2016

Oh yes, absolutely – I think it’s rather fundamental – at least in my use-cases. I think it should be configurable as well regarding reconnect timeout, enable/disable, …

@erossignon
Copy link
Member

as agreed with @pelis, let close this issue. original timeout problem is now fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants