fix(lmxproxy): make MxAccess client name unique per instance
Multiple instances registering with the same name may cause MxAccess to conflict on callback routing. ClientName is now configurable via appsettings.json, defaulting to a GUID-suffixed name if not set. Instances A and B use "LmxProxy-A" and "LmxProxy-B" respectively. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,12 +8,13 @@ Two instances of the LmxProxy v2 Host service are deployed on windev (10.100.0.4
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **Service Name** | `ZB.MOM.WW.LmxProxy.Host.V2` | `ZB.MOM.WW.LmxProxy.Host.V2B` |
|
| **Service Name** | `ZB.MOM.WW.LmxProxy.Host.V2` | `ZB.MOM.WW.LmxProxy.Host.V2B` |
|
||||||
| **Display Name** | SCADA Bridge LMX Proxy V2 | SCADA Bridge LMX Proxy V2B |
|
| **Display Name** | SCADA Bridge LMX Proxy V2 | SCADA Bridge LMX Proxy V2B |
|
||||||
|
| **MxAccess Client Name** | `LmxProxy-A` | `LmxProxy-B` |
|
||||||
| **Publish Directory** | `C:\publish-v2\` | `C:\publish-v2b\` |
|
| **Publish Directory** | `C:\publish-v2\` | `C:\publish-v2b\` |
|
||||||
| **gRPC Port** | 50100 | 50101 |
|
| **gRPC Port** | 50100 | 50101 |
|
||||||
| **HTTP Status Port** | 8081 | 8082 |
|
| **HTTP Status Port** | 8081 | 8082 |
|
||||||
| **Log File Prefix** | `lmxproxy-v2-` | `lmxproxy-v2b-` |
|
| **Log File Prefix** | `lmxproxy-v2-` | `lmxproxy-v2b-` |
|
||||||
| **Log Directory** | `C:\publish-v2\logs\` | `C:\publish-v2b\logs\` |
|
| **Log Directory** | `C:\publish-v2\logs\` | `C:\publish-v2b\logs\` |
|
||||||
| **Health Probe Tag** | `DevAppEngine.Scheduler.ScanTime` | `DevAppEngine.Scheduler.ScanTime` |
|
| **Health Probe Tag** | `DevPlatform.Scheduler.ScanTime` | `DevPlatform.Scheduler.ScanTime` |
|
||||||
| **API Keys File** | `C:\publish-v2\apikeys.json` | `C:\publish-v2b\apikeys.json` |
|
| **API Keys File** | `C:\publish-v2\apikeys.json` | `C:\publish-v2b\apikeys.json` |
|
||||||
| **Auto-Start** | Yes | Yes |
|
| **Auto-Start** | Yes | Yes |
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ namespace ZB.MOM.WW.LmxProxy.Host.Configuration
|
|||||||
/// <summary>Path to API key configuration file. Default: apikeys.json.</summary>
|
/// <summary>Path to API key configuration file. Default: apikeys.json.</summary>
|
||||||
public string ApiKeyConfigFile { get; set; } = "apikeys.json";
|
public string ApiKeyConfigFile { get; set; } = "apikeys.json";
|
||||||
|
|
||||||
|
/// <summary>Unique client name for MxAccess Register(). Must be unique per instance. Default: auto-generated.</summary>
|
||||||
|
public string? ClientName { get; set; }
|
||||||
|
|
||||||
/// <summary>MxAccess connection settings.</summary>
|
/// <summary>MxAccess connection settings.</summary>
|
||||||
public ConnectionConfiguration Connection { get; set; } = new ConnectionConfiguration();
|
public ConnectionConfiguration Connection { get; set; } = new ConnectionConfiguration();
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,8 @@ namespace ZB.MOM.WW.LmxProxy.Host
|
|||||||
probeTestTagAddress: _config.HealthCheck.TestTagAddress,
|
probeTestTagAddress: _config.HealthCheck.TestTagAddress,
|
||||||
probeTimeoutMs: _config.HealthCheck.ProbeTimeoutMs,
|
probeTimeoutMs: _config.HealthCheck.ProbeTimeoutMs,
|
||||||
maxConsecutiveTransportFailures: _config.HealthCheck.MaxConsecutiveTransportFailures,
|
maxConsecutiveTransportFailures: _config.HealthCheck.MaxConsecutiveTransportFailures,
|
||||||
degradedProbeIntervalMs: _config.HealthCheck.DegradedProbeIntervalMs);
|
degradedProbeIntervalMs: _config.HealthCheck.DegradedProbeIntervalMs,
|
||||||
|
clientName: _config.ClientName);
|
||||||
|
|
||||||
// 5. Connect to MxAccess synchronously (with timeout)
|
// 5. Connect to MxAccess synchronously (with timeout)
|
||||||
Log.Information("Connecting to MxAccess (timeout: {Timeout}s)...",
|
Log.Information("Connecting to MxAccess (timeout: {Timeout}s)...",
|
||||||
|
|||||||
@@ -107,8 +107,9 @@ namespace ZB.MOM.WW.LmxProxy.Host.MxAccess
|
|||||||
_lmxProxy.OnDataChange += OnDataChange;
|
_lmxProxy.OnDataChange += OnDataChange;
|
||||||
_lmxProxy.OnWriteComplete += OnWriteComplete;
|
_lmxProxy.OnWriteComplete += OnWriteComplete;
|
||||||
|
|
||||||
// Register with MxAccess
|
// Register with MxAccess using unique client name
|
||||||
_connectionHandle = _lmxProxy.Register("ZB.MOM.WW.LmxProxy.Host");
|
_connectionHandle = _lmxProxy.Register(_clientName);
|
||||||
|
Log.Information("Registered with MxAccess as '{ClientName}'", _clientName);
|
||||||
|
|
||||||
if (_connectionHandle <= 0)
|
if (_connectionHandle <= 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace ZB.MOM.WW.LmxProxy.Host.MxAccess
|
|||||||
private readonly bool _autoReconnect;
|
private readonly bool _autoReconnect;
|
||||||
private readonly string? _nodeName;
|
private readonly string? _nodeName;
|
||||||
private readonly string? _galaxyName;
|
private readonly string? _galaxyName;
|
||||||
|
private readonly string _clientName;
|
||||||
|
|
||||||
private readonly SemaphoreSlim _readSemaphore;
|
private readonly SemaphoreSlim _readSemaphore;
|
||||||
private readonly SemaphoreSlim _writeSemaphore;
|
private readonly SemaphoreSlim _writeSemaphore;
|
||||||
@@ -81,7 +82,8 @@ namespace ZB.MOM.WW.LmxProxy.Host.MxAccess
|
|||||||
string? probeTestTagAddress = null,
|
string? probeTestTagAddress = null,
|
||||||
int probeTimeoutMs = 5000,
|
int probeTimeoutMs = 5000,
|
||||||
int maxConsecutiveTransportFailures = 3,
|
int maxConsecutiveTransportFailures = 3,
|
||||||
int degradedProbeIntervalMs = 30000)
|
int degradedProbeIntervalMs = 30000,
|
||||||
|
string? clientName = null)
|
||||||
{
|
{
|
||||||
_maxConcurrentOperations = maxConcurrentOperations;
|
_maxConcurrentOperations = maxConcurrentOperations;
|
||||||
_readTimeoutMs = readTimeoutSeconds * 1000;
|
_readTimeoutMs = readTimeoutSeconds * 1000;
|
||||||
@@ -94,6 +96,7 @@ namespace ZB.MOM.WW.LmxProxy.Host.MxAccess
|
|||||||
_probeTimeoutMs = probeTimeoutMs;
|
_probeTimeoutMs = probeTimeoutMs;
|
||||||
_maxConsecutiveTransportFailures = maxConsecutiveTransportFailures;
|
_maxConsecutiveTransportFailures = maxConsecutiveTransportFailures;
|
||||||
_degradedProbeIntervalMs = degradedProbeIntervalMs;
|
_degradedProbeIntervalMs = degradedProbeIntervalMs;
|
||||||
|
_clientName = clientName ?? "LmxProxy-" + Guid.NewGuid().ToString("N").Substring(0, 8);
|
||||||
|
|
||||||
_readSemaphore = new SemaphoreSlim(maxConcurrentOperations, maxConcurrentOperations);
|
_readSemaphore = new SemaphoreSlim(maxConcurrentOperations, maxConcurrentOperations);
|
||||||
_writeSemaphore = new SemaphoreSlim(maxConcurrentOperations, maxConcurrentOperations);
|
_writeSemaphore = new SemaphoreSlim(maxConcurrentOperations, maxConcurrentOperations);
|
||||||
|
|||||||
Reference in New Issue
Block a user