让我们假设有一个简单的用例(java / microservice /事件源/事件):
让我们假设B出于某种技术原因不能更改用户名,但是A本身允许更改用户名。
如何实施?在经典的整体作品中,我们可能会围绕 java.beans.VetoableChangeSupport。在微服务中,我遇到了麻烦。我的第一个想法是将其分为三个事件。
首先,我们发布一个事件,说明“用户名将被更改”。每当微服务B不喜欢时,第二个事件将是“取消用户名更改”。第三个事件是“用户名更改成功”。
到目前为止,它将起作用。但是我们如何实现呢?我不喜欢将所有微服务连接在一起的整体。我喜欢一些“插件”概念。只要我们不运行微服务B,就不会有人进行否决,我们将自动运行“用户名更改成功”。但是,一旦我们运行微服务B,我们就应该检查微服务B是否喜欢否决该事件。
我们如何将“微服务B未运行”从“微服务B当前处于脱机状态,但很快就会回来”呢?在第一种情况下,我们没有否决权。在第二种情况下,我们必须等待B再次回来检查未决的“用户名已更改”事件。
答案 0 :(得分:0)
如果您不希望依赖于微服务B,那么我只允许最初更改名称并将对微服务B的拒绝视为最终的一致性异常。
因此,在微服务A中,您将尽最大努力确保更改不会引起与MS-B同步的问题。然后,记录“用户名已更改”事件。
如果MS-B不在运行,则说明您已完成操作,名称已更改。
如果MS-B 正在运行,并且在尝试同步更新的用户名时遇到问题,那么您将进入更正模式。确切的说,这取决于许多因素(问题发生的可能性,影响是什么,等等)。
您可能需要MS-B暂停并发送电子邮件,以便人工纠正情况。
否则,您可能让MS-B发出了撤消更改(另一个“用户名更改”或“名称更改恢复回X:-对您的域有意义的任何东西”)。
如果您发布补偿事件,则需要注意一些额外的例外情况,例如<?php
# Connection info
$hostname = 'server\instance,port';
$dbname = 'dbname';
$username = 'username';
$password = 'password';
# Connection
try {
$dbh = new PDO("sqlsrv:server=$hostname;Database=$dbname", $username, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch( PDOException $e ) {
die( "Error connecting to SQL Server. ".$e->getMessage());
}
# Statement
try {
$user_id = 123;
$stat_id = 321;
$val = '000';
$stmt = $dbh->prepare('insert into user_stats (user_id, stat_id, value) values (:user, :stat, :val)');
$stmt->bindParam(':user', $user_id);
$stmt->bindParam(':stat', $stat_id);
$stmt->bindParam(':val', $val); // OK, using bindParam() and a variaable
//$stmt->bindValue(':val', '111'); // OK, using bindValue()
//$stmt->bindParam(':val', '0'); // Error
$stmt->execute();
} catch( PDOException $e ) {
die( "Error connecting to SQL Server".$e->getMessage() );
}
$stmt = null;
# End
$dbh = null;
?>
将其名称更改为User A
,然后User X
然后将其名称更改为User B
。如果MS-B撤消了第一个名称更改,除非您也撤消了第二个名称更改,否则将使用重复的名称。
(或者,您可以在允许重新使用旧用户名之前将其“锁定”一定时间。)