Event Ruler (der Kürze halber im Rest des Dokuments Ruler genannt) ist eine Java-Bibliothek, die den Abgleich von Regeln mit Ereignissen ermöglicht. Ein Ereignis ist eine Liste von Feldern, die als Name/Wert-Paare oder als JSON-Objekt angegeben werden können. Eine Regel verknüpft Ereignisfeldnamen mit Listen möglicher Werte. Es gibt zwei Gründe, Ruler zu verwenden:
Inhalt:
Am einfachsten lässt es sich anhand eines Beispiels erklären.
Ein Ereignis ist ein JSON-Objekt. Hier ist ein Beispiel:
{
"version" : "0" ,
"id" : "ddddd4-aaaa-7777-4444-345dd43cc333" ,
"detail-type" : "EC2 Instance State-change Notification" ,
"source" : "aws.ec2" ,
"account" : "012345679012" ,
"time" : "2017-10-02T16:24:49Z" ,
"region" : "us-east-1" ,
"resources" : [
"arn:aws:ec2:us-east-1:123456789012:instance/i-000000aaaaaa00000"
] ,
"detail" : {
"c-count" : 5 ,
"d-count" : 3 ,
"x-limit" : 301.8 ,
"source-ip" : "10.0.0.33" ,
"instance-id" : "i-000000aaaaaa00000" ,
"state" : "running"
}
}
Sie können dies auch als eine Reihe von Name/Wert-Paaren sehen. Der Kürze halber präsentieren wir nur eine Auswahl. Ruler verfügt über APIs zum Bereitstellen von Ereignissen sowohl im JSON-Format als auch als Name/Wert-Paare:
+--------------+------------------------------------------+
| name | value |
|--------------|------------------------------------------|
| source | "aws.ec2" |
| detail-type | "EC2 Instance State-change Notification" |
| detail.state | "running" |
+--------------+------------------------------------------+
Ereignisse im JSON-Formular können in Form eines rohen JSON-Strings oder eines geparsten Jackson JsonNode bereitgestellt werden.
Die Regeln in diesem Abschnitt entsprechen alle dem obigen Beispielereignis:
{
"detail-type" : [ "EC2 Instance State-change Notification" ] ,
"resources" : [ "arn:aws:ec2:us-east-1:123456789012:instance/i-000000aaaaaa00000" ] ,
"detail" : {
"state" : [ "initializing" , "running" ]
}
}
Dadurch wird jedes Ereignis mit den bereitgestellten Werten für die Werte resource
, detail-type
und detail.state
abgeglichen, wobei alle anderen Felder im Ereignis ignoriert werden. Es würde auch übereinstimmen, wenn der Wert von detail.state
"initializing"
gewesen wäre.
Werte in Regeln werden immer als Arrays bereitgestellt und stimmen überein, wenn der Wert im Ereignis einer der im Array bereitgestellten Werte ist. Der Verweis auf resources
zeigt, dass die Regel zutrifft, wenn der Wert im Ereignis ebenfalls ein Array ist, wenn die Schnittmenge zwischen dem Ereignisarray und dem Regelarray nicht leer ist.
{
"time" : [ { "prefix" : "2017-10-02" } ]
}
Präfixübereinstimmungen funktionieren nur bei Feldern mit Zeichenfolgenwerten.
{
"source" : [ { "prefix" : { "equals-ignore-case" : "EC2" } } ]
}
Übereinstimmungen mit dem Präfix „equals-ignore-case“ funktionieren nur bei Feldern mit Zeichenfolgenwerten.
{
"source" : [ { "suffix" : "ec2" } ]
}
Suffixübereinstimmungen funktionieren nur bei Feldern mit Zeichenfolgenwerten.
{
"source" : [ { "suffix" : { "equals-ignore-case" : "EC2" } } ]
}
Suffix-Equals-Ignore-Case-Übereinstimmungen funktionieren nur bei Feldern mit Zeichenfolgenwerten.
{
"source" : [ { "equals-ignore-case" : "EC2" } ]
}
Gleichheits-Ignorieren-Groß-/Kleinschreibung-Übereinstimmungen funktionieren nur bei Feldern mit Zeichenfolgenwerten.
{
"source" : [ { "wildcard" : "Simple*Service" } ]
}
Platzhalterübereinstimmungen funktionieren nur bei Feldern mit Zeichenfolgenwerten. Ein einzelner Wert kann null bis viele Platzhalterzeichen enthalten, aufeinanderfolgende Platzhalterzeichen sind jedoch nicht zulässig. Um das Sternchen gezielt zuzuordnen, kann ein Platzhalterzeichen mit einem Backslash maskiert werden. Zwei aufeinanderfolgende Backslashes (also ein mit einem Backslash maskierter Backslash) repräsentieren das eigentliche Backslash-Zeichen. Ein Backslash, der ein anderes Zeichen als ein Sternchen oder einen Backslash ersetzt, ist nicht zulässig.
„Anything-but-Matching“ macht das, was der Name verspricht: passt alles außer dem, was in der Regel vorgesehen ist.
Anything-but funktioniert mit einzelnen Zeichenfolgen und numerischen Werten oder Listen, die ausschließlich Zeichenfolgen oder ausschließlich numerische Werte enthalten müssen. Es kann auch auf ein Präfix, Suffix oder eine Gleichheits-Groß-/Kleinschreibungsübereinstimmung einer Zeichenfolge oder einer Liste von Zeichenfolgen angewendet werden.
Einzelnes Alles-außer (Zeichenfolge, dann numerisch):
{
"detail" : {
"state" : [ { "anything-but" : "initializing" } ]
}
}
{
"detail" : {
"x-limit" : [ { "anything-but" : 123 } ]
}
}
Alles andere als Liste (Strings):
{
"detail" : {
"state" : [ { "anything-but" : [ "stopped" , "overloaded" ] } ]
}
}
Alles andere als Liste (Zahlen):
{
"detail" : {
"x-limit" : [ { "anything-but" : [ 100 , 200 , 300 ] } ]
}
}
Alles andere als Präfix:
{
"detail" : {
"state" : [ { "anything-but" : { "prefix" : "init" } } ]
}
}
Alles andere als Präfixliste (Strings):
{
"detail" : {
"state" : [ { "anything-but" : { "prefix" : [ "init" , "error" ] } } ]
}
}
Alles andere als Suffix:
{
"detail" : {
"instance-id" : [ { "anything-but" : { "suffix" : "1234" } } ]
}
}
Alles andere als Suffixliste (Strings):
{
"detail" : {
"instance-id" : [ { "anything-but" : { "suffix" : [ "1234" , "6789" ] } } ]
}
}
Alles andere als den Fall ignorieren:
{
"detail" : {
"state" : [ { "anything-but" : { "equals-ignore-case" : "Stopped" } } ]
}
}
Alles-außer-Fall-Ignorieren-Liste (Zeichenfolgen):
{
"detail" : {
"state" : [ { "anything-but" : { "equals-ignore-case" : [ "Stopped" , "OverLoaded" ] } } ]
}
}
Alles andere als ein Platzhalter:
{
"detail" : {
"state" : [ { "anything-but" : { "wildcard" : "*/bin/*.jar" } } ]
}
}
Alles andere als Platzhalterliste (Strings):
{
"detail" : {
"state" : [ { "anything-but" : { "wildcard" : [ "*/bin/*.jar" , "*/bin/*.class" ] } } ]
}
}
{
"detail" : {
"c-count" : [ { "numeric" : [ ">" , 0 , "<=" , 5 ] } ] ,
"d-count" : [ { "numeric" : [ "<" , 10 ] } ] ,
"x-limit" : [ { "numeric" : [ "=" , 3.018e2 ] } ]
}
}
Oben veranschaulichen die Verweise auf c-count
, d-count
und x-limit
den numerischen Abgleich und funktionieren nur mit Werten, die JSON-Zahlen sind. Der numerische Abgleich unterstützt die gleiche Genauigkeit und den gleichen Bereich wie double
von Java, das binary64
-Standard IEEE 754 implementiert.
{
"detail" : {
"source-ip" : [ { "cidr" : "10.0.0.0/24" } ]
}
}
Dies funktioniert auch mit IPv6-Adressen.
Der Exists-Abgleich hängt davon ab, ob ein Feld im JSON-Ereignis vorhanden ist oder nicht.
Die folgende Regel gilt für jedes Ereignis, bei dem ein detail.c-count-Feld vorhanden ist.
{
"detail" : {
"c-count" : [ { "exists" : true } ]
}
}
Die folgende Regel gilt für alle Ereignisse, die kein detail.c-count-Feld haben.
{
"detail" : {
"c-count" : [ { "exists" : false } ]
}
}
Hinweis: Die Übereinstimmung „ Exists
“ funktioniert nur auf den Blattknoten. Es funktioniert nicht auf Zwischenknoten.
Als Beispiel würde das obige Beispiel für exists : false
mit dem folgenden Ereignis übereinstimmen:
{
"detail-type" : [ "EC2 Instance State-change Notification" ] ,
"resources" : [ "arn:aws:ec2:us-east-1:123456789012:instance/i-000000aaaaaa00000" ] ,
"detail" : {
"state" : [ "initializing" , "running" ]
}
}
würde aber auch mit dem folgenden Ereignis übereinstimmen, da c-count
kein Blattknoten ist:
{
"detail-type" : [ "EC2 Instance State-change Notification" ] ,
"resources" : [ "arn:aws:ec2:us-east-1:123456789012:instance/i-000000aaaaaa00000" ] ,
"detail" : {
"state" : [ "initializing" , "running" ]
"c-count" : {
"c1" : 100
}
}
}
{
"time" : [ { "prefix" : "2017-10-02" } ] ,
"detail" : {
"state" : [ { "anything-but" : "initializing" } ] ,
"c-count" : [ { "numeric" : [ ">" , 0 , "<=" , 5 ] } ] ,
"d-count" : [ { "numeric" : [ "<" , 10 ] } ] ,
"x-limit" : [ { "anything-but" : [ 100 , 200 , 300 ] } ] ,
"source-ip" : [ { "cidr" : "10.0.0.0/8" } ]
}
}
Wie die obigen Beispiele zeigen, betrachtet Ruler eine Regel als übereinstimmend, wenn alle in der Regel genannten Felder übereinstimmen, und er betrachtet ein Feld als übereinstimmend, wenn einer der bereitgestellten Feldwerte übereinstimmt, d. h. Ruler hat die „Und“-Logik angewendet standardmäßig auf alle Felder ohne „Und“-Grundelement erforderlich .
Es gibt zwei Möglichkeiten, die „Oder“-Effekte zu erreichen:
Das Grundelement „$or“ ermöglicht es dem Kunden, die „Oder“-Beziehung zwischen Feldern in der Regel direkt zu beschreiben.
Das Lineal erkennt die „Oder“-Beziehung nur , wenn die Regel alle folgenden Bedingungen erfüllt:
/src/main/software/amazon/event/ruler/Constants.java#L38
Die folgende Regel wird beispielsweise nicht als „geparst“ Oder“-Beziehung, da „numerisch“ und „Präfix“ vom Ruler reservierte Schlüsselwörter sind. {
"$or": [ {"numeric" : 123}, {"prefix": "abc"} ]
}
Andernfalls behandelt Ruler das „$or“ einfach als normalen Dateinamen genauso wie andere Zeichenfolgen in der Regel.
Normales „Oder“:
// Effect of "source" && ("metricName" || "namespace")
{
"source" : [ "aws.cloudwatch" ] ,
"$or" : [
{ "metricName" : [ "CPUUtilization" , "ReadLatency" ] } ,
{ "namespace" : [ "AWS/EC2" , "AWS/ES" ] }
]
}
Paralleles „Oder“:
// Effect of ("metricName" || "namespace") && ("detail.source" || "detail.detail-type")
{
"$or" : [
{ "metricName" : [ "CPUUtilization" , "ReadLatency" ] } ,
{ "namespace" : [ "AWS/EC2" , "AWS/ES" ] }
] ,
"detail" : {
"$or" : [
{ "source" : [ "aws.cloudwatch" ] } ,
{ "detail-type" : [ "CloudWatch Alarm State Change" ] }
]
}
}
„Oder“ enthält ein „Und“.
// Effect of ("source" && ("metricName" || ("metricType && "namespace") || "scope"))
{
"source" : [ "aws.cloudwatch" ] ,
"$or" : [
{ "metricName" : [ "CPUUtilization" , "ReadLatency" ] } ,
{
"metricType" : [ "MetricType" ] ,
"namespace" : [ "AWS/EC2" , "AWS/ES" ]
} ,
{ "scope" : [ "Service" ] }
]
}
Verschachtelte „Oder“ und „Und“
// Effect of ("source" && ("metricName" || ("metricType && "namespace" && ("metricId" || "spaceId")) || "scope"))
{
"source" : [ "aws.cloudwatch" ] ,
"$or" : [
{ "metricName" : [ "CPUUtilization" , "ReadLatency" ] } ,
{
"metricType" : [ "MetricType" ] ,
"namespace" : [ "AWS/EC2" , "AWS/ES" ] ,
"$or" : [
{ "metricId" : [ 1234 ] } ,
{ "spaceId" : [ 1000 ] }
]
} ,
{ "scope" : [ "Service" ] }
]
}
„$or“ wird in einigen Anwendungen möglicherweise bereits als normaler Schlüssel verwendet (obwohl dies wahrscheinlich selten vorkommt). In diesen Fällen versucht Ruler sein Bestes, die Abwärtskompatibilität aufrechtzuerhalten. Nur wenn die drei oben genannten Bedingungen erfüllt sind, ändert sich das Verhalten des Herrschers, da davon ausgegangen wird, dass Ihre Regel wirklich ein ODER wollte und bis heute falsch konfiguriert wurde. Die folgende Regel funktioniert beispielsweise weiterhin wie eine normale Regel und behandelt „$or“ als normalen Feldnamen in der Regel und im Ereignis:
{
"source" : [ "aws.cloudwatch" ] ,
"$or" : {
"metricType" : [ "MetricType" ] ,
"namespace" : [ "AWS/EC2" , "AWS/ES" ]
}
}
Weitere Beispiele dafür, wie „$or“ von Ruler als normaler Feldname analysiert wird, finden Sie unter /src/test/data/normalRulesWithOrWording.json
.
Das Schlüsselwort „$or“ als „Or“-Beziehungsprimitiv sollte nicht als normales Feld sowohl in Ereignissen als auch in Regeln entworfen werden. Ruler unterstützt die alten Regeln, bei denen „$or“ als normaler Feldname geparst wird, um die Abwärtskompatibilität aufrechtzuerhalten und dem Team Zeit zu geben, die alte „$or“-Verwendung von ihren Ereignissen und Regeln als normalen Dateinamen zu migrieren. Die gemischte Verwendung von „$or“ als „Or“-Grundelement und „$or“ als normaler Feldname wird von Ruler absichtlich nicht unterstützt, um das Auftreten der äußerst unangenehmen Mehrdeutigkeiten bei „$or“ zu vermeiden.
Es gibt zwei Möglichkeiten, Ruler zu verwenden. Sie können mehrere Regeln in einer „Maschine“ kompilieren und dann entweder die rulesForEvent()
Methode oder rulesForJSONEvent()
Methode verwenden, um zu prüfen, welche der Regeln mit einem Ereignis übereinstimmen. Der Unterschied zwischen diesen beiden Methoden wird im Folgenden erläutert. In dieser Diskussion wird rulesForEvent()
generisch verwendet, außer dort, wo der Unterschied wichtig ist.
Alternativ können Sie eine einzelne statische boolesche Methode verwenden, um zu bestimmen, ob ein einzelnes Ereignis einer bestimmten Regel entspricht.
Es gibt eine einzige statische boolesche Methode Ruler.matchesRule(event, rule)
– beide Argumente werden als JSON-Strings bereitgestellt.
HINWEIS: Es gibt eine weitere veraltete Methode namens Ruler.matches(event, rule)
die nicht verwendet werden sollte, da ihre Ergebnisse nicht mit rulesForJSONEvent()
und rulesForEvent()
übereinstimmen. Weitere Informationen finden Sie in der Dokumentation zu Ruler.matches(event, rule)
.
Die Übereinstimmungszeit hängt nicht von der Anzahl der Regeln ab. Dies ist die beste Wahl, wenn Sie mehrere mögliche Regeln zur Auswahl haben und insbesondere, wenn Sie die kompilierte Maschine speichern können.
Die Übereinstimmungszeit wird durch den Grad des Nichtdeterminismus beeinflusst, der durch Wildcard- und Alles-außer-Wildcard-Regeln verursacht wird. Die Leistung nimmt ab, wenn immer mehr Platzhalterregelpräfixe mit einem theoretischen Worst-Case-Ereignis übereinstimmen. Um dies zu vermeiden, sollten Platzhalterregeln, die sich auf dasselbe Ereignisfeld beziehen, gemeinsame Präfixe vor dem ersten Platzhalterzeichen vermeiden. Wenn ein gemeinsames Präfix erforderlich ist, verwenden Sie die Mindestanzahl an Platzhalterzeichen und begrenzen Sie sich wiederholende Zeichenfolgen, die nach einem Platzhalterzeichen auftreten. MachineComplexityEvaluator kann verwendet werden, um eine Maschine zu bewerten und den Grad des Nichtdeterminismus oder der „Komplexität“ zu bestimmen (dh wie viele Wildcard-Regelpräfixe mit einem theoretischen Worst-Case-Ereignis übereinstimmen). Hier sind einige Datenpunkte, die einen typischen Leistungsabfall bei steigenden Komplexitätswerten zeigen.
Es ist wichtig, die Komplexität der Maschine zu begrenzen, um Ihre Anwendung zu schützen. Zur Begrenzung der Maschinenkomplexität gibt es mindestens zwei unterschiedliche Strategien. Was sinnvoller ist, hängt möglicherweise von Ihrer Anwendung ab.
Strategie Nr. 1 ist idealer, da sie die tatsächliche Komplexität der Maschine misst, die alle Regeln enthält. Wenn möglich, sollte diese Strategie verwendet werden. Der Nachteil besteht darin, dass Sie beispielsweise über eine Steuerungsebene verfügen, die die Erstellung jeweils einer Regel bis zu einer sehr großen Anzahl ermöglicht. Anschließend müssen Sie für jede dieser Steuerungsebenenoperationen alle vorhandenen Regeln laden, um die Validierung durchzuführen. Das könnte sehr teuer werden. Es ist auch anfällig für Rennbedingungen. Strategie Nr. 2 ist ein Kompromiss. Der von Strategie Nr. 2 verwendete Schwellenwert ist niedriger als der von Strategie Nr. 1, da es sich um einen Schwellenwert pro Regel handelt. Nehmen wir an, Sie möchten, dass die Komplexität einer Maschine mit allen hinzugefügten Regeln nicht mehr als 300 beträgt. Dann könnten Sie mit Strategie Nr. 2 beispielsweise jede Maschine mit einer einzigen Regel auf eine Komplexität von 10 begrenzen und 30 Regeln mit Platzhaltermustern zulassen . Im absolut schlimmsten Fall, in dem die Komplexität perfekt additiv ist (unwahrscheinlich), würde dies zu einer Maschine mit einer Komplexität von 300 führen. Der Nachteil besteht darin, dass es unwahrscheinlich ist, dass die Komplexität perfekt additiv ist, und die Anzahl der Regeln, die Platzhalter enthalten, daher auch wahrscheinlich unnötig eingeschränkt werden.
Für Strategie Nr. 2 muss je nach Art der Speicherung der Regeln möglicherweise ein zusätzliches Attribut zu den Regeln hinzugefügt werden, um anzugeben, welche Regeln nicht deterministisch sind (d. h. Platzhaltermuster enthalten), um die Anzahl der Regeln, die Platzhalter enthalten, zu begrenzen.
Das Folgende ist ein Codeausschnitt, der veranschaulicht, wie die Komplexität für ein bestimmtes Muster begrenzt werden kann, z. B. für Strategie Nr. 2.
public class Validate {
private void validate ( String pattern , MachineComplexityEvaluator machineComplexityEvaluator ) {
// If we cannot compile, then return exception.
List < Map < String , List < Patterns >>> compilationResult = Lists . newArrayList ();
try {
compilationResult . addAll ( JsonRuleCompiler . compile ( pattern ));
} catch ( Exception e ) {
InvalidPatternException internalException =
EXCEPTION_FACTORY . invalidPatternException ( e . getLocalizedMessage ());
throw ExceptionMapper . mapToModeledException ( internalException );
}
// Validate wildcard patterns. Look for wildcard patterns out of all patterns that have been used.
Machine machine = new Machine ();
int i = 0 ;
for ( Map < String , List < Patterns >> rule : compilationResult ) {
if ( containsWildcard ( rule )) {
// Add rule to machine for complexity evaluation.
machine . addPatternRule ( Integer . toString (++ i ), rule );
}
}
// Machine has all rules containing wildcard match types. See if the complexity is under the limit.
int complexity = machine . evaluateComplexity ( machineComplexityEvaluator );
if ( complexity > MAX_MACHINE_COMPLEXITY ) {
InvalidPatternException internalException = EXCEPTION_FACTORY . invalidPatternException ( "Rule is too complex" );
throw ExceptionMapper . mapToModeledException ( internalException );
}
}
private boolean containsWildcard ( Map < String , List < Patterns >> rule ) {
for ( List < Patterns > fieldPatterns : rule . values ()) {
for ( Patterns fieldPattern : fieldPatterns ) {
if ( fieldPattern . type () == WILDCARD || fieldPattern . type () == ANYTHING_BUT_WILDCARD ) {
return true ;
}
}
}
return false ;
}
}
Die Hauptklasse, mit der Sie interagieren, implementiert den Regelabgleich auf Zustandsmaschinenbasis. Die interessanten Methoden sind:
addRule()
– fügt der Maschine eine neue Regel hinzudeleteRule()
– löscht eine Regel vom ComputerrulesForEvent()
/ rulesForJSONEvent()
– findet die Regeln in der Maschine, die einem Ereignis entsprechen Es gibt zwei Varianten: Machine
und GenericMachine<T>
. Maschine ist einfach GenericMachine<String>
. Die API bezeichnet den generischen Typ als „Name“, was den Verlauf widerspiegelt: Die String-Version wurde zuerst erstellt und die von ihr gespeicherten und zurückgegebenen Strings wurden als Regelnamen betrachtet.
Aus Sicherheitsgründen sollte der zum „Benennen“ von Regeln verwendete Typ unveränderlich sein. Wenn Sie den Inhalt eines Objekts ändern, während es als Regelname verwendet wird, kann dies zu Funktionsstörungen von Ruler führen.
Die GenericMachine- und Machine-Konstruktoren akzeptieren optional ein GenericMachineConfiguration-Objekt, das die folgenden Konfigurationsoptionen verfügbar macht.
Standard: false Normalerweise werden NameStates für eine bestimmte Schlüsseluntersequenz und ein bestimmtes Muster wiederverwendet, wenn diese Schlüsseluntersequenz und dieses Muster zuvor hinzugefügt wurden oder wenn für die angegebene Schlüsseluntersequenz bereits ein Muster hinzugefügt wurde. Daher ist die Wiederverwendung von NameState standardmäßig opportunistisch. Wenn Sie dieses Flag jedoch auf „true“ setzen, wird die Wiederverwendung von NameState für eine Schlüsseluntersequenz erzwungen. Dies bedeutet, dass das erste Muster, das für eine Schlüsseluntersequenz hinzugefügt wird, einen NameState wiederverwendet, wenn diese Schlüsseluntersequenz zuvor hinzugefügt wurde. Das bedeutet, dass jede Schlüsseluntersequenz einen einzelnen NameState hat. Dies verbessert die Speicherauslastung in einigen Fällen exponentiell, führt jedoch dazu, dass mehr Unterregeln in einzelnen NameStates gespeichert werden, die Ruler manchmal durchläuft, was zu einer geringfügigen Leistungseinbuße bei der Laufzeit führen kann. Aus Gründen der Abwärtskompatibilität ist dieser Wert standardmäßig auf „false“ eingestellt, aber wahrscheinlich würden alle bis auf die latenzempfindlichsten Anwendungen von der Einstellung auf „true“ profitieren.
Hier ist ein einfaches Beispiel. Halten:
machine . addRule ( "0" , "{"key1": ["a", "b", "c"]}" ) ;
Das Muster „a“ erstellt einen NameState, und selbst mit „additionalNameStateReuse=false“ verwenden das zweite Muster („b“) und das dritte Muster („c“) denselben NameState erneut. Aber bedenken Sie stattdessen Folgendes:
machine . addRule ( "0" , "{"key1": ["a"]}" ) ;
machine . addRule ( "1" , "{"key1": ["b"]}" ) ;
machine . addRule ( "2" , "{"key1": ["c"]}" ) ;
Mit „additionalNameStateReuse=false“ erhalten wir nun drei NameStates, da das erste Muster, das bei jeder Regelergänzung für eine Schlüsselteilsequenz angetroffen wird, einen neuen NameState erstellt. „a“, „b“ und „c“ erhalten also alle ihre eigenen NameStates. Mit „additionalNameStateReuse=true“ erstellt „a“ jedoch einen neuen NameState und „b“ und „c“ verwenden dann denselben NameState wieder. Dies wird dadurch erreicht, dass wir speichern, dass wir bereits einen NameState für die Schlüsseluntersequenz „key1“ haben.
Beachten Sie, dass es keine Rolle spielt, ob jede addRule einen anderen Regelnamen oder denselben Regelnamen verwendet.
Alle Formen dieser Methode haben das gleiche erste Argument, einen String, der den Namen der Regel bereitstellt und von rulesForEvent()
zurückgegeben wird. Die restlichen Argumente stellen die Name/Wert-Paare bereit. Sie können wie in den obigen Beispielen in JSON bereitgestellt werden (über einen String, einen Reader, einen InputStream oder byte[]
) oder als Map<String, List<String>>
, wobei die Schlüssel die Feldnamen und die sind Werte sind die Liste möglicher Übereinstimmungen; Im obigen Beispiel gäbe es einen Schlüssel mit dem Namen detail.state
, dessen Wert die Liste mit "initializing"
und "running"
wäre.
Hinweis: Diese Methode (und auch deleteRule()
) ist synchronisiert, sodass zu jedem Zeitpunkt möglicherweise nur ein Thread die Maschine aktualisiert.