We have a Forms environment where there is a Primary Forms server that runs the Routing Service that is not in the NLB and then 3 Forms servers that are in an NLB. Reading the Network Load Balancing for Laserfiche Web Products paper, it is assuming that the Routing Service is part of the NLB. My question is, is there anything different from what is listed in the paper to setup our environment correctly with the setup we have? We are using Forms 10.4.4.444 and will not be upgrading to Forms 11 yet.
Question
Question
Answer
The identity is only required when the Routing Service is running with a domain user, the white paper doesn't make it clear. The online help has been updated to make it more accurate. We have an updated version for the white paper but it was not uploaded to the support site yet, it will be updated soon.
The lfpushnotification need to be changed as well since we only need to have one notification service running for one system. I updated my original reply.
Since you have the Primary Forms Server with Routing Service and Notification Service running on a seperate machine, you need to configure the Forms servers in the cluster to connect to the Routing Service and Notification Service on the Primary Forms Server machine.
You can either disable the Routing Service, Notification Service on other machines or leave them running, the status of them will not affect the system since they are not in use.
Replies
If the Primary Forms Server that runs the Routing Service is not in the NLB cluster, you just need following change in the web.config for the Forms servers in the NLB cluster to connect to the Routing Service:
<client> <endpoint address="net.tcp://{routing-service-machine-address}:8168/lfrouting" binding="netTcpBinding" bindingConfiguration="timeoutBinding" contract="Laserfiche.Forms.Routing.IRoutingEngineService" name="" /> <endpoint address="net.tcp://{routing-service-machine-address}:8268/lfpushnotification" binding="netTcpBinding" bindingConfiguration="timeoutBinding" contract="Laserfiche.PushNotificationService.SharedContracts.IPushNotificationService" name="" /> <endpoint address="net.tcp://{routing-service-machine-address}:8732/lfautotrigger" binding="netTcpBinding" bindingConfiguration="timeoutBinding" contract="FormsModel.SharedContracts.IAutoTrigger" name="" /> <endpoint address="net.tcp://{routing-service-machine-address}:8736/lfformexport" binding="netTcpBinding" bindingConfiguration="timeoutBinding" contract="FormsModel.SharedContracts.IFormExportService" name="" /> <endpoint address="http://localhost:5048/LicenseManager/service" binding="ws2007HttpBinding" bindingConfiguration="WS2007HttpBinding_ILicenseManager" contract="LicenseManagerService.ILicenseManager" name="LicenseManagerService"> <identity /> </endpoint> <endpoint address="http://localhost:5048/LicenseManager/service" binding="ws2007HttpBinding" bindingConfiguration="WS2007HttpBinding_ILicenseManager" contract="LicenseManagerService.ILicenseManager2" name="LicenseManagerService2"> <identity /> </endpoint> <endpoint address="http://localhost:5048/LicenseManager/sts" binding="ws2007HttpBinding" bindingConfiguration="WS2007HttpBinding_ILFSecurityTokenService" contract="LicenseManagerSTS.ILFSecurityTokenService" name="LicenseManagerSTS"> <identity /> </endpoint> <endpoint address="net.tcp://{routing-service-machine-address}:8738/lflicensing" binding="netTcpBinding" bindingConfiguration="timeoutBinding" contract="FormsModel.SharedContracts.ILicensingService" name="" /> <endpoint address="net.tcp://{routing-service-machine-address}:8170/attachmentTransfer" binding="netTcpBinding" bindingConfiguration="timeoutBindingStreamed" contract="FormsModel.SharedContracts.IAttachmentTransferService" name="" /> </client>
replace {routing-service-machine-address} with the actual machine name.
For clarification, the /lfpushnotification does not need to be changed? Also, in the whitepaper it says to insert the
<identity><userPrincipalName value ="{someone@example.com}" /></identity>
Is that needed?
I am also guessing that the "Laserfiche Notification Hub Service" and "Laserfiche Notification Master Service" services need to be disabled on each NLB server? The whitepaper does not specify that, only the Forms Routing Service.
The identity is only required when the Routing Service is running with a domain user, the white paper doesn't make it clear. The online help has been updated to make it more accurate. We have an updated version for the white paper but it was not uploaded to the support site yet, it will be updated soon.
The lfpushnotification need to be changed as well since we only need to have one notification service running for one system. I updated my original reply.
Since you have the Primary Forms Server with Routing Service and Notification Service running on a seperate machine, you need to configure the Forms servers in the cluster to connect to the Routing Service and Notification Service on the Primary Forms Server machine.
You can either disable the Routing Service, Notification Service on other machines or leave them running, the status of them will not affect the system since they are not in use.
On step 4 of the online help instructions, does it have to be the cluster IP address or can it be the cluster full internet name? If so, can that be updated accordingly?
It can be either cluster IP address or cluster full internet name, we will update the document accordingly.
I have been working on this configuration today and have been unable to get the real-time notifications to work. I have turned off both the Notification Hub Service and Master Service on the LB servers and edited the \forms\web.config files as referenced in the online help.
When I look at F12 Developer Tools it shows 'Failed to load resource: the server responded with a status of 500 ()'.
If I hit the Primary Forms server that is running the Notification service directly the real-time notifications work, so I'm sure it has something to do with traffic flowing through the LB.
The Forms\App\Operational logs for the LB servers give the following warning message:
Log Name: Laserfiche-Forms-App/Operational Source: Laserfiche-Forms-App Date: 2/8/2023 3:19:30 PM Event ID: 28100 Task Category: NotificationServerConnectionDownWarning Level: Warning Keywords: Session0,Session1,Session2,Session3 User: XXXXXX Computer: XXXXXX Description: A connection to the notification server could not be made. Notifications and real-time updates have been disabled. [LFF8100-NotificationServerConnectionDown] Details: URL: /Forms/webapi/v1/notification/GetPushNotificationToken?forceNew=false&skipErrMsg=true Error: NotificationServerConnectionDown Date: 2/8/2023 3:19:30 PM (US Mountain Standard Time) HTTP Status Code: 500 Business Process ID: 0 User: XXXXXX IP: 10.96.8.10 Browser: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.78 Stack Trace: Caught exception: Laserfiche.Forms.CommonUtils.Exceptions.LFFormsException Message: A connection to the notification server could not be made. Notifications and real-time updates have been disabled. [LFF8100-NotificationServerConnectionDown] at E_Forms.WebApi.Version1.Controllers.NotificationController.GetPushNotificationTokenGeneral(PushServiceRegisterRequest registerReq, Boolean forceNew) at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass6_2.<GetExecutor>b__2(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__6.MoveNext() Event Xml: <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"> <System> <Provider Name="Laserfiche-Forms-App" Guid="{98141CA4-660B-51C6-66B4-EC37F5B2FD87}" /> <EventID>28100</EventID> <Version>0</Version> <Level>3</Level> <Task>37434</Task> <Opcode>0</Opcode> <Keywords>0x8000f00000000000</Keywords> <TimeCreated SystemTime="2023-02-08T22:19:30.688450700Z" /> <EventRecordID>541</EventRecordID> <Correlation /> <Execution ProcessID="8560" ThreadID="10628" /> <Channel>Laserfiche-Forms-App/Operational</Channel> <Computer>XXXXXX</Computer> <Security UserID="XXXXXX" /> </System> <EventData> <Data Name="message">A connection to the notification server could not be made. Notifications and real-time updates have been disabled. [LFF8100-NotificationServerConnectionDown] Details: URL: /Forms/webapi/v1/notification/GetPushNotificationToken?forceNew=false&skipErrMsg=true Error: NotificationServerConnectionDown Date: 2/8/2023 3:19:30 PM (US Mountain Standard Time) HTTP Status Code: 500 Business Process ID: 0 User: XXXXXX IP: XXXXXX Browser: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.78 Stack Trace: Caught exception: Laserfiche.Forms.CommonUtils.Exceptions.LFFormsException Message: A connection to the notification server could not be made. Notifications and real-time updates have been disabled. [LFF8100-NotificationServerConnectionDown] at E_Forms.WebApi.Version1.Controllers.NotificationController.GetPushNotificationTokenGeneral(PushServiceRegisterRequest registerReq, Boolean forceNew) at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass6_2.<GetExecutor>b__2(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__6.MoveNext() </Data> </EventData> </Event>
Your setup is still "Primary Forms server that runs the Routing Service that is not in the NLB and then 3 Forms servers that are in an NLB"? And the real-time notification doesn't work when access the NLB web server from a machine that is not in the NLB? For the Forms servers in the NLB, you have configured to use notification service on the primary Forms Server right?
You need to make sure the ports (8268 for lfpushnotification 8181 for the Notification Hub Service) are opened between the primary Forms server and the NLB cluster.
For "When I look at F12 Developer Tools it shows 'Failed to load resource: the server responded with a status of 500 ()'.", what does the request URL looks like? Does it containt "8181//signalr/"? which is the request to the notification hub server from the web browser?
Follow two diagrams show how the real-time notification work:
- The web browser(Client) need to be able to access the Hub Service(LF Push Hub) using port 8181.
- The Forms server(Forms) need to be able to access the Master Service(LF Push Master) using port 8268.
- The Master Server(LF Push Master) need to be able to access Forms server (using port 8268) and Hub Service(using port 8181).
I'm still looking into everything that you sent, but thought I would at least send you the Request URL for the 500 error: https://xxxx.xxxx.com/Forms/webapi/v1/notification/GetPushNotificationToken?forceNew=false&skipErrMsg=true
Just for easier reading, would you mind adding ports to each of the numbers in both diagrams?
After checking with a couple of teams at our organization I have decided to move the Primary Forms Server into the LB. We will end up increasing its CPU and RAM accordingly. I am still running into the same issue on the secondary server, but I will start a new post for the issue since the configuration of our servers has changed.
@████████ how does this type of scenario where the Primary Forms server is not in the cluster change the instructions for 'Configuring a Forms Routing Service Cluster'?