Event Ruler(나머지 문서에서는 간결하게 Ruler라고 함)는 Rules 를 Events 와 일치시킬 수 있는 Java 라이브러리입니다. 이벤트는 이름/값 쌍 또는 JSON 개체로 제공될 수 있는 필드 목록입니다. 규칙은 이벤트 필드 이름을 가능한 값 목록과 연결합니다. 눈금자를 사용하는 이유는 두 가지입니다.
내용물:
예를 들어 설명하는 것이 가장 쉽습니다.
이벤트는 JSON 개체입니다. 예는 다음과 같습니다.
{
"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"
}
}
이를 이름/값 쌍 세트로 볼 수도 있습니다. 간결함을 위해 샘플링만 제시합니다. Ruler에는 JSON 형식과 이름/값 쌍으로 이벤트를 제공하기 위한 API가 있습니다.
+--------------+------------------------------------------+
| name | value |
|--------------|------------------------------------------|
| source | "aws.ec2" |
| detail-type | "EC2 Instance State-change Notification" |
| detail.state | "running" |
+--------------+------------------------------------------+
JSON 형식의 이벤트는 원시 JSON 문자열 또는 구문 분석된 Jackson JsonNode 형식으로 제공될 수 있습니다.
이 섹션의 규칙은 모두 위의 샘플 이벤트와 일치합니다.
{
"detail-type" : [ "EC2 Instance State-change Notification" ] ,
"resources" : [ "arn:aws:ec2:us-east-1:123456789012:instance/i-000000aaaaaa00000" ] ,
"detail" : {
"state" : [ "initializing" , "running" ]
}
}
이는 이벤트의 다른 필드를 무시하고 모든 이벤트를 resource
, detail-type
및 detail.state
값에 대해 제공된 값과 일치시킵니다. detail.state
의 값이 "initializing"
인 경우에도 일치합니다.
규칙의 값은 항상 배열로 제공되며 이벤트의 값이 배열에 제공된 값 중 하나인 경우 일치합니다. resources
에 대한 참조는 이벤트의 값도 배열인 경우 이벤트 배열과 규칙 배열 간의 교차점이 비어 있지 않으면 규칙이 일치함을 보여줍니다.
{
"time" : [ { "prefix" : "2017-10-02" } ]
}
접두사 일치는 문자열 값 필드에서만 작동합니다.
{
"source" : [ { "prefix" : { "equals-ignore-case" : "EC2" } } ]
}
접두어 같음-대소문자 무시 일치는 문자열 값 필드에서만 작동합니다.
{
"source" : [ { "suffix" : "ec2" } ]
}
접미사 일치는 문자열 값 필드에서만 작동합니다.
{
"source" : [ { "suffix" : { "equals-ignore-case" : "EC2" } } ]
}
접미사 같음-대소문자 무시 일치는 문자열 값 필드에서만 작동합니다.
{
"source" : [ { "equals-ignore-case" : "EC2" } ]
}
같음-대소문자 무시 일치는 문자열 값 필드에서만 작동합니다.
{
"source" : [ { "wildcard" : "Simple*Service" } ]
}
와일드카드 일치는 문자열 값 필드에서만 작동합니다. 단일 값에는 0개 이상의 와일드카드 문자가 포함될 수 있지만 연속된 와일드카드 문자는 허용되지 않습니다. 별표 문자와 구체적으로 일치시키려면 와일드카드 문자를 백슬래시로 이스케이프할 수 있습니다. 두 개의 연속 백슬래시(즉, 백슬래시로 이스케이프된 백슬래시)는 실제 백슬래시 문자를 나타냅니다. 별표 또는 백슬래시 이외의 문자를 이스케이프하는 백슬래시는 허용되지 않습니다.
일치를 제외한 모든 항목은 이름에서 알 수 있듯이 규칙에 제공된 항목을 제외한 모든 항목과 일치합니다.
무엇이든 가능하지만 전체 문자열 또는 전체 숫자를 포함해야 하는 단일 문자열 및 숫자 값 또는 목록과 함께 작동합니다. 또한 문자열이나 문자열 목록의 접두사, 접미사 또는 대소문자 무시 일치에 적용될 수도 있습니다.
단일 항목(문자열, 숫자 순):
{
"detail" : {
"state" : [ { "anything-but" : "initializing" } ]
}
}
{
"detail" : {
"x-limit" : [ { "anything-but" : 123 } ]
}
}
목록(문자열)을 제외한 모든 것:
{
"detail" : {
"state" : [ { "anything-but" : [ "stopped" , "overloaded" ] } ]
}
}
목록(숫자)을 제외한 모든 것:
{
"detail" : {
"x-limit" : [ { "anything-but" : [ 100 , 200 , 300 ] } ]
}
}
접두사를 제외한 모든 것:
{
"detail" : {
"state" : [ { "anything-but" : { "prefix" : "init" } } ]
}
}
접두사 목록(문자열)을 제외한 모든 것:
{
"detail" : {
"state" : [ { "anything-but" : { "prefix" : [ "init" , "error" ] } } ]
}
}
접미사를 제외한 모든 것:
{
"detail" : {
"instance-id" : [ { "anything-but" : { "suffix" : "1234" } } ]
}
}
접미사 목록(문자열)을 제외한 모든 것:
{
"detail" : {
"instance-id" : [ { "anything-but" : { "suffix" : [ "1234" , "6789" ] } } ]
}
}
대소문자 무시를 제외한 모든 것:
{
"detail" : {
"state" : [ { "anything-but" : { "equals-ignore-case" : "Stopped" } } ]
}
}
대소문자 무시를 제외한 모든 목록(문자열):
{
"detail" : {
"state" : [ { "anything-but" : { "equals-ignore-case" : [ "Stopped" , "OverLoaded" ] } } ]
}
}
와일드카드를 제외한 모든 것:
{
"detail" : {
"state" : [ { "anything-but" : { "wildcard" : "*/bin/*.jar" } } ]
}
}
와일드카드 목록(문자열)을 제외한 모든 것:
{
"detail" : {
"state" : [ { "anything-but" : { "wildcard" : [ "*/bin/*.jar" , "*/bin/*.class" ] } } ]
}
}
{
"detail" : {
"c-count" : [ { "numeric" : [ ">" , 0 , "<=" , 5 ] } ] ,
"d-count" : [ { "numeric" : [ "<" , 10 ] } ] ,
"x-limit" : [ { "numeric" : [ "=" , 3.018e2 ] } ]
}
}
위에서 c-count
, d-count
및 x-limit
에 대한 참조는 숫자 일치를 보여주며 JSON 숫자 값에만 작동합니다. 숫자 일치는 IEEE 754 binary64
표준을 구현하는 Java의 double
기본 요소와 동일한 정밀도와 범위를 지원합니다.
{
"detail" : {
"source-ip" : [ { "cidr" : "10.0.0.0/24" } ]
}
}
이는 IPv6 주소에서도 작동합니다.
존재 일치는 JSON 이벤트에 필드가 있는지 여부에 따라 작동합니다.
아래 규칙은 Detail.c-count 필드가 있는 모든 이벤트와 일치합니다.
{
"detail" : {
"c-count" : [ { "exists" : true } ]
}
}
아래 규칙은 Detail.c-count 필드가 없는 모든 이벤트와 일치합니다.
{
"detail" : {
"c-count" : [ { "exists" : false } ]
}
}
참고 Exists
일치는 리프 노드에서만 작동합니다. 중간 노드에서는 작동하지 않습니다.
예를 들어, exists : false
에 대한 위의 예는 아래 이벤트와 일치합니다.
{
"detail-type" : [ "EC2 Instance State-change Notification" ] ,
"resources" : [ "arn:aws:ec2:us-east-1:123456789012:instance/i-000000aaaaaa00000" ] ,
"detail" : {
"state" : [ "initializing" , "running" ]
}
}
그러나 c-count
리프 노드가 아니기 때문에 아래 이벤트와도 일치합니다.
{
"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" } ]
}
}
위의 예에서 볼 수 있듯이 Ruler는 규칙에 명명된 모든 필드가 일치하면 일치할 규칙을 고려하고 제공된 필드 값 중 하나라도 일치하면 일치할 필드로 간주합니다. 즉, Ruler가 "And" 논리를 적용했습니다. 기본적으로 "And" 프리미티브 없이 모든 필드에 필요합니다 .
"Or" 효과를 얻는 방법에는 두 가지가 있습니다.
고객이 규칙의 필드 간 "Or" 관계를 직접 설명할 수 있도록 하는 "$or" 기본 요소입니다.
눈금자는 규칙이 아래 조건을 모두 충족하는 경우 에만 "Or" 관계를 인식합니다.
/src/main/software/amazon/event/ruler/Constants.java#L38
의 RESERVED_FIELD_NAMES_IN_OR_RELATIONSHIP을 참조하세요. 예를 들어 아래 규칙은 " 또는 "숫자"와 "접두사"가 눈금자 예약 키워드이기 때문에 "관계입니다. {
"$or": [ {"numeric" : 123}, {"prefix": "abc"} ]
}
그렇지 않으면 Ruler는 "$or"를 규칙의 다른 문자열과 동일한 일반 파일 이름으로 처리합니다.
일반 "또는":
// Effect of "source" && ("metricName" || "namespace")
{
"source" : [ "aws.cloudwatch" ] ,
"$or" : [
{ "metricName" : [ "CPUUtilization" , "ReadLatency" ] } ,
{ "namespace" : [ "AWS/EC2" , "AWS/ES" ] }
]
}
병렬 "또는":
// 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" ] }
]
}
}
"Or" 안에 "And"가 들어있어요
// Effect of ("source" && ("metricName" || ("metricType && "namespace") || "scope"))
{
"source" : [ "aws.cloudwatch" ] ,
"$or" : [
{ "metricName" : [ "CPUUtilization" , "ReadLatency" ] } ,
{
"metricType" : [ "MetricType" ] ,
"namespace" : [ "AWS/EC2" , "AWS/ES" ]
} ,
{ "scope" : [ "Service" ] }
]
}
중첩된 "Or" 및 "And"
// 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"는 이미 일부 응용 프로그램에서 일반 키로 사용되었을 수 있습니다(드물기는 하지만). 이러한 경우 Ruler는 이전 버전과의 호환성을 유지하기 위해 최선을 다합니다. 위에서 언급한 3가지 조건이 충족된 경우에만 규칙이 실제로 OR을 원했고 오늘까지 잘못 구성되었다고 가정하기 때문에 눈금자의 동작이 변경됩니다. 예를 들어, 아래 규칙은 규칙 및 이벤트에서 "$or"를 일반 필드 이름으로 처리하여 일반 규칙으로 계속 작동합니다.
{
"source" : [ "aws.cloudwatch" ] ,
"$or" : {
"metricType" : [ "MetricType" ] ,
"namespace" : [ "AWS/EC2" , "AWS/ES" ]
}
}
"$or"가 Ruler에 의해 일반 필드 이름으로 구문 분석되는 추가 예는 /src/test/data/normalRulesWithOrWording.json
을 참조하세요.
"Or" 관계 기본 요소인 "$or" 키워드는 이벤트와 규칙 모두에서 일반 필드로 설계되어서는 안 됩니다. Ruler는 "$or"가 일반 필드 이름으로 구문 분석되어 이전 버전과의 호환성을 유지하고 팀이 이벤트 및 규칙에서 일반 파일 이름으로 레거시 "$or" 사용을 마이그레이션할 수 있는 시간을 제공하는 레거시 규칙을 지원합니다. "$or"를 "Or" 프리미티브로 사용하고 "$or"를 일반 필드 이름으로 혼합 사용하는 것은 "$or"에 대한 매우 어색한 모호성이 발생하는 것을 피하기 위해 Ruler에서 의도적으로 지원하지 않습니다.
눈금자를 사용하는 방법에는 두 가지가 있습니다. 여러 규칙을 "머신"으로 컴파일한 다음 해당 rulesForEvent()
메서드 또는 rulesForJSONEvent()
메서드 중 하나를 사용하여 어떤 규칙이 이벤트와 일치하는지 확인할 수 있습니다. 이 두 가지 방법의 차이점은 아래에 설명되어 있습니다. 이 토론에서는 차이점이 중요한 경우를 제외하고 일반적으로 rulesForEvent()
사용합니다.
또는 단일 정적 부울 메서드를 사용하여 개별 이벤트가 특정 규칙과 일치하는지 확인할 수 있습니다.
단일 정적 부울 메서드 Ruler.matchesRule(event, rule)
이 있습니다. 두 인수 모두 JSON 문자열로 제공됩니다.
참고: Ruler.matches(event, rule)
라는 더 이상 사용되지 않는 또 다른 메서드가 있습니다. 이 메서드의 결과는 rulesForJSONEvent()
및 rulesForEvent()
와 일치하지 않으므로 사용하면 안 됩니다. 자세한 내용은 Ruler.matches(event, rule)
문서를 참조하세요.
일치 시간은 규칙 수에 따라 달라지지 않습니다. 선택할 수 있는 규칙이 여러 개 있고 특히 컴파일된 기계를 저장할 방법이 있는 경우 이것이 최선의 선택입니다.
일치 시간은 와일드카드 및 와일드카드 이외의 규칙으로 인해 발생하는 비결정성 정도의 영향을 받습니다. 이론적으로 최악의 경우와 일치하는 와일드카드 규칙 접두사의 수가 증가하면 성능이 저하됩니다. 이를 방지하려면 동일한 이벤트 필드와 관련된 와일드카드 규칙은 첫 번째 와일드카드 문자로 이어지는 공통 접두사를 피해야 합니다. 공통 접두사가 필요한 경우 최소 개수의 와일드카드 문자를 사용하고 와일드카드 문자 다음에 나타나는 반복 문자 시퀀스를 제한합니다. MachineComplexityEvaluator를 사용하면 기계를 평가하고 비결정성 또는 "복잡성"의 정도(예: 이론적 최악의 이벤트와 일치하는 와일드카드 규칙 접두어 수)를 결정할 수 있습니다. 다음은 복잡성 점수 증가에 따른 일반적인 성능 저하를 보여주는 몇 가지 데이터 포인트입니다.
애플리케이션을 보호하려면 기계 복잡성을 제한하는 것이 중요합니다. 기계 복잡성을 제한하기 위한 전략에는 최소한 두 가지가 있습니다. 어느 것이 더 적합한지는 애플리케이션에 따라 달라질 수 있습니다.
전략 #1은 모든 규칙을 포함하는 기계의 실제 복잡성을 측정한다는 점에서 더 이상적입니다. 가능하다면 이 전략을 사용해야 합니다. 단점은 한 번에 하나의 규칙을 매우 많은 수까지 생성할 수 있는 제어 평면이 있다고 가정해 보겠습니다. 그런 다음 이러한 각 제어 영역 작업에 대해 모든 기존 규칙을 로드하여 검증을 수행해야 합니다. 이것은 매우 비쌀 수 있습니다. 또한 경쟁 조건이 발생하기 쉽습니다. 전략 #2는 타협입니다. 전략 #2에서 사용되는 임계값은 규칙별 임계값이므로 전략 #1보다 낮습니다. 모든 규칙을 추가한 상태에서 머신의 복잡도를 300 이하로 만들고 싶다고 가정해 보겠습니다. 예를 들어 전략 #2를 사용하면 각 단일 규칙 머신의 복잡도를 10으로 제한하고 와일드카드 패턴이 포함된 30개의 규칙을 허용할 수 있습니다. . 복잡성이 완벽하게 가산되는(가능성 없음) 최악의 경우에는 복잡성이 300인 시스템이 됩니다. 단점은 복잡성이 완전히 가산될 가능성이 낮다는 것입니다. 따라서 와일드카드가 포함된 규칙의 수는 불필요하게 제한될 가능성이 높습니다.
전략 #2의 경우, 규칙이 저장되는 방식에 따라 와일드카드가 포함된 규칙의 수를 제한하기 위해 규칙이 비결정적(예: 와일드카드 패턴 포함)인지 나타내기 위해 추가 속성을 규칙에 추가해야 할 수도 있습니다.
다음은 전략 #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 ; } }
상호 작용할 기본 클래스는 상태 머신 기반 규칙 일치를 구현합니다. 흥미로운 방법은 다음과 같습니다.
addRule()
- 시스템에 새 규칙을 추가합니다.deleteRule()
- 시스템에서 규칙을 삭제합니다.rulesForEvent()
/ rulesForJSONEvent()
- 이벤트와 일치하는 시스템의 규칙을 찾습니다. Machine
과 GenericMachine
의 두 가지 종류가 있습니다. 기계는 단순히 GenericMachine
입니다. API는 내역을 반영하는 "이름"으로 일반 유형을 참조합니다. 문자열 버전이 먼저 구축되었으며 저장 및 반환된 문자열은 규칙 이름으로 간주되었습니다.
안전을 위해 규칙의 "이름 지정"에 사용되는 유형은 변경할 수 없어야 합니다. 규칙 이름으로 사용되는 개체의 내용을 변경하면 Ruler의 작동이 중단될 수 있습니다.
GenericMachine 및 Machine 생성자는 선택적으로 다음 구성 옵션을 노출하는 GenericMachineConfiguration 개체를 허용합니다.
기본값: false 일반적으로 이 키 하위 시퀀스와 패턴이 이전에 추가되었거나 지정된 키 하위 시퀀스에 대해 패턴이 이미 추가된 경우 지정된 키 하위 시퀀스 및 패턴에 대해 NameStates가 재사용됩니다. 따라서 기본적으로 NameState 재사용은 기회에 따라 이루어집니다. 그러나 이 플래그를 true로 설정하면 키 하위 시퀀스에 대해 NameState 재사용이 강제됩니다. 즉, 키 하위 시퀀스에 추가되는 첫 번째 패턴은 해당 키 하위 시퀀스가 이전에 추가된 경우 NameState를 재사용합니다. 즉, 각 키 하위 시퀀스에는 단일 NameState가 있습니다. 이로 인해 경우에 따라 메모리 활용도가 기하급수적으로 향상되지만 개별 NameStates에 더 많은 하위 규칙이 저장되어 Ruler가 때때로 반복하여 런타임 성능이 약간 저하될 수 있습니다. 이전 버전과의 호환성을 위해 기본값은 false이지만 대기 시간에 가장 민감한 애플리케이션을 제외한 모든 응용 프로그램은 이를 true로 설정하면 이점을 얻을 수 있습니다.
다음은 간단한 예입니다. 고려하다:
machine . addRule ( "0" , "{"key1": ["a", "b", "c"]}" ) ;
패턴 "a"는 NameState를 생성하고, 추가NameStateReuse=false를 사용해도 두 번째 패턴("b")과 세 번째 패턴("c")은 동일한 NameState를 재사용합니다. 하지만 대신 다음을 고려해보세요.
machine . addRule ( "0" , "{"key1": ["a"]}" ) ;
machine . addRule ( "1" , "{"key1": ["b"]}" ) ;
machine . addRule ( "2" , "{"key1": ["c"]}" ) ;
이제 extraNameStateReuse=false를 사용하면 세 개의 NameState가 됩니다. 각 규칙 추가 시 키 하위 시퀀스에 대해 발견된 첫 번째 패턴이 새 NameState를 생성하기 때문입니다. 따라서 "a", "b" 및 "c"는 모두 고유한 NameState를 갖습니다. 그러나 extraNameStateReuse=true를 사용하면 "a"는 새 NameState를 생성하고 "b"와 "c"는 이 동일한 NameState를 재사용합니다. 이는 키 하위 시퀀스 "key1"에 대한 NameState가 이미 있음을 저장하여 수행됩니다.
각 addRule이 다른 규칙 이름을 사용하는지, 동일한 규칙 이름을 사용하는지 여부는 중요하지 않습니다.
이 메소드의 모든 형태는 동일한 첫 번째 인수, 즉 규칙의 이름을 제공하고 rulesForEvent()
에 의해 반환되는 문자열을 갖습니다. 나머지 인수는 이름/값 쌍을 제공합니다. 위의 예(String, Reader, InputStream 또는 byte[]
통해)와 같이 JSON으로 제공되거나 Map
으로 제공될 수 있습니다. 여기서 키는 필드 이름이고 값은 가능한 일치 목록입니다. 위의 예를 사용하면 "initializing"
및 "running"
포함하는 목록이 값이 되는 detail.state
라는 키가 있습니다.
참고: 이 메서드(및 deleteRule()
)는 동기화되므로 언제든지 하나의 스레드만 시스템을 업데이트할 수 있습니다.
이름은 같지만 여러 다른 이름/값 패턴을 사용하여 addRule()
여러 번 호출할 수 있으므로 "또는" 관계를 얻을 수 있습니다. rulesForEvent()
패턴 중 하나라도 일치하면 해당 이름을 반환합니다.
예를 들어 규칙 이름이 "R1"인 addRule()
호출하고 다음 패턴을 추가한다고 가정합니다.
{
"detail" : {
"c-count" : [ { "numeric" : [ ">" , 0 , "<=" , 5 ] } ]
}
}
그런 다음 동일한 이름이지만 다른 패턴으로 다시 호출합니다.
{
"detail" : {
"x-limit" : [ { "numeric" : [ "=" , 3.018e2 ] } ]
}
}
그 후, rulesForEvent()
c-count
값 2 또는 x-limit
값 301.8에 대해 "R1"을 반환합니다.
이것은 addRule()
의 미러 이미지입니다. 각각의 경우 첫 번째 인수는 문자열로 제공되는 규칙 이름입니다. 후속 인수는 이름과 값을 제공하며 addRule()
과 동일한 방식으로 제공될 수 있습니다.
참고: 이 메소드(및 addRule()
)는 동기화되므로 언제든지 하나의 스레드만 시스템을 업데이트할 수 있습니다.
이 API의 작동은 미묘할 수 있습니다. 기계는 규칙 이름에 대한 이름/값 패턴의 매핑을 유한 자동 장치로 컴파일하지만 어떤 패턴이 주어진 규칙 이름에 매핑되는지 기억하지 못합니다. 따라서 deleteRule()
의 패턴이 해당 addRule()
의 패턴과 정확히 일치할 필요는 없습니다. 눈금자는 이름/값 패턴과 일치하는 항목을 찾아 제공된 이름을 가진 규칙과 일치하는지 확인하고, 그렇다면 제거합니다. 해당 addRule()
호출과 정확히 일치하지 않는 deleteRule()
호출을 수행하면 실패하지 않고 시스템을 일관성 없는 상태로 두지 않지만 시스템에 "쓰레기"가 쌓일 수 있다는 점을 명심하세요.
구체적인 결과는 위의 규칙 및 규칙 이름 섹션에 설명된 것처럼 이름은 같지만 패턴이 다른 addRule()
여러 번 호출한 경우 동일한 횟수로 deleteRule()
호출해야 한다는 것입니다. 관련 패턴을 사용하여 해당 규칙 이름에 대한 모든 참조를 시스템에서 제거합니다.
이 메소드는 제공된 이벤트와 일치하는 규칙의 이름이 포함된 Machine의 경우 List
(및 GenericMachine의 경우 List
)을 반환합니다. 이벤트는 JSON 형식을 나타내는 단일 String
로 두 메서드 중 하나에 제공될 수 있습니다.
이벤트는 필드 이름과 값을 대체하는 문자열 컬렉션으로 rulesForEvent()
에 제공될 수도 있으며 필드 이름별로 어휘적으로 정렬되어야 합니다. 이는 List
또는 String[]
일 수 있습니다.
JSON으로 이벤트를 제공하는 것이 권장되는 접근 방식이며 여러 가지 장점이 있습니다. 우선, 이름/값 수량을 교대로 사용하여 문자열 목록이나 배열을 이름별로 정렬된 순서로 채우는 것은 까다로우며 Ruler는 도움이 되지 않으며 목록이 부적절하게 구조화되면 제대로 작동하지 않습니다. 게다가 문자열로 제공되는 필드 값의 표현은 JSON 구문 규칙을 따라야 합니다. 아래 JSON 텍스트 일치 항목을 참조하세요.
마지막으로, 이벤트의 목록/배열 버전으로 인해 Ruler가 배열 구조를 인식하고 배열 일관성 일치를 제공하는 것이 불가능합니다. 이에 대해서는 이 문서에서 아래에 설명되어 있습니다. rulesForEvent(String eventJSON)
API는 배열 일관성 일치를 지원하지 않기 때문에 특히 rulesForJSONEvent()
를 위해 더 이상 사용되지 않습니다.
rulesForJSONEvent()
에는 이벤트의 JSON 형식을 정렬된 목록으로 바꾸는 코드가 광범위하게 프로파일링되고 최적화되었다는 장점도 있습니다.
rulesForEvent()
및 rulesForJSONEvent()
의 성능은 addRule()
로 추가된 규칙 수에 따라 달라지지 않습니다. rulesForJSONEvent()
최적화된 이벤트 처리로 인해 일반적으로 더 빠릅니다. 자체 이벤트 처리를 수행하고 미리 정렬된 이름 및 값 목록을 사용하여 rulesForEvent()
호출하는 경우 훨씬 더 빠릅니다. 하지만 rulesForJSONEvent()
만큼 빠르게 필드 목록 준비를 수행하지 못할 수도 있습니다.
이 방법은 대략적으로 기계 내의 개체 수입니다. 해당 값은 규칙이 추가되거나 제거될 때에만 달라집니다. 이는 잠재적으로 많은 메모리가 필요할 수 있는 대형 시스템을 식별하는 데 유용합니다. 이 방법은 내부 개체 수에 따라 달라지므로 눈금자 라이브러리 내부가 변경되면 이 개수가 변경될 수 있습니다. 이 방법은 메모리를 차지하고 대규모 규칙 시스템의 영향을 악화시키는 것을 방지하기 위해 런타임에 모든 계산을 수행합니다. 규칙 평가 및 시스템 변경 차단을 방지하기 위해 해당 계산은 의도적으로 스레드로부터 안전하지 않습니다. 이는 병렬 프로세스가 머신에 추가되거나 제거되는 경우 해당 병렬 프로세스가 완료될 때와 다른 결과를 얻을 수 있음을 의미합니다. 또한 라이브러리는 일부 패턴에 대해 내부를 최적화하므로(자세한 내용은 ShortcutTransition.java
참조) 규칙이 추가되거나 제거된 순서에 따라 다른 결과를 얻을 수도 있습니다.
이벤트를 중첩된 JSON 스타일 문서가 아닌 이름/값 쌍으로 생각하는 경우 Patterns
클래스(및 해당 Range
하위 클래스)가 규칙을 구성하는 데 유용할 수 있습니다. 다음 정적 메서드가 유용합니다.
public static ValuePatterns exactMatch ( final String value );
public static ValuePatterns prefixMatch ( final String prefix );
public static ValuePatterns prefixEqualsIgnoreCaseMatch ( final String prefix );
public static ValuePatterns suffixMatch ( final String suffix );
public static ValuePatterns suffixEqualsIgnoreCaseMatch ( final String suffix );
public static ValuePatterns equalsIgnoreCaseMatch ( final String value );
public static ValuePatterns wildcardMatch ( final String value );
public static AnythingBut anythingButMatch ( final String anythingBut );
public static AnythingBut anythingButMatch ( final Set < String > anythingButs );
public static AnythingBut anythingButMatch ( final double anythingBut );
public static AnythingBut anythingButNumberMatch ( final Set < Double > anythingButs );
public static AnythingButValuesSet anythingButPrefix ( final String prefix );
public static AnythingButValuesSet anythingButPrefix ( final Set < String > anythingButs );
public static AnythingButValuesSet anythingButSuffix ( final String suffix );
public static AnythingButValuesSet anythingButSuffix ( final Set < String > anythingButs );
public static AnythingButValuesSet anythingButIgnoreCaseMatch ( final String anythingBut );
public static AnythingButValuesSet anythingButIgnoreCaseMatch ( final Set < String > anythingButs );
public static AnythingButValuesSet anythingButWildcard ( final String value );
public static AnythingButValuesSet anythingButWildcard ( final Set < String > anythingButs );
public static ValuePatterns numericEquals ( final double val );
public static Range lessThan ( final double val );
public static Range lessThanOrEqualTo ( final double val );
public static Range greaterThan ( final double val );
public static Range greaterThanOrEqualTo ( final double val );
public static Range between ( final double bottom , final boolean openBottom , final double top , final boolean openTop );
이러한 방법으로 적절한 Patterns
일치자를 구성한 후에는 다음 방법을 사용하여 컴퓨터에 추가하거나 삭제할 수 있습니다.
public void addPatternRule ( final String name , final Map < String , List < Patterns >> namevals );
public void deletePatternRule ( final String name , final Map < String , List < Patterns >> namevals );
참고: deleteRule()
에 나열된 주의 사항은 deletePatternRule()
에도 적용됩니다.
규칙의 필드 값은 JSON 표현으로 제공되어야 합니다. 즉, 문자열 값은 "따옴표"로 묶어야 합니다. 숫자( -3.0e5
) 및 특정 JSON 관련 리터럴( true
, false
및 null
)과 같이 따옴표가 없는 값이 허용됩니다.
규칙이 JSON 형식으로 addRule()
()에 제공되거나 리터럴 문자열이 아닌 패턴으로 작업하는 경우 이는 완전히 무시될 수 있습니다. 그러나 규칙을 이름/값 쌍으로 제공하고 "xyz" 필드가 "true" 문자열과 일치하도록 지정하려는 경우 해당 문자열은 "xyz", ""true""
로 표현되어야 합니다. 반면에 "xyz", "true"
JSON 리터럴 true
와만 일치합니다.
Ruler는 배열이 포함된 이벤트에 대한 규칙 일치를 지원하지만 이벤트가 JSON 형식으로 제공되는 경우에만 지원합니다. 사전 정렬된 필드 목록인 경우 이벤트의 배열 구조가 손실됩니다. 또한 동작은 rulesForEvent()
또는 rulesForJSONEvent
사용하는지 여부에 따라 달라집니다.
다음 이벤트를 고려해보세요.
{
"employees" : [
{ "firstName" : "John" , "lastName" : "Doe" } ,
{ "firstName" : "Anna" , "lastName" : "Smith" } ,
{ "firstName" : "Peter" , "lastName" : "Jones" }
]
}
그러면 이 규칙은 다음과 일치합니다.
{ "employees" : { "firstName" : [ "Anna" ] } }
즉, 배열 구조는 규칙 패턴에서 "분리"되고 포함된 모든 객체는 마치 상위 필드의 값인 것처럼 처리됩니다. 이는 다중 레벨 배열에서도 작동합니다.
{
"employees" : [
[
{ "firstName" : "John" , "lastName" : "Doe" } ,
{ "firstName" : "Anna" , "lastName" : "Smith" }
] ,
[
{ "firstName" : "Peter" , "lastName" : "Jones" }
]
]
}
이전 버전의 Ruler에서 유일한 기계 기반 일치 방법은 rulesForEvent()
였지만 불행하게도 다음 규칙과도 일치합니다.
{ "employees" : { "firstName" : [ "Anna" ] , "lastName" : [ "Jones" ] } }
수정 사항으로 Ruler는 이름에서 알 수 있듯이 JSON 형식으로 제공된 이벤트만 일치시키는 rulesForJSONEvent()
도입했습니다. rulesForJsonEvent()
위의 "Anna"/"Jones" 규칙과 일치 하지 않습니다 .
공식적으로: rulesForJSONEvent()
동일한 배열의 서로 다른 요소에 있는 JSON 객체 내에 두 필드가 있는 일치 항목을 인식하지 않습니다. 실제로 이는 예상한 대로 작동한다는 의미입니다.
지원 클래스 com.amazon.fsm.ruler.RuleCompiler
가 있습니다. 여기에는 JSON 규칙 정의를 승인하고 문자열 값을 반환하는 check()
라는 메서드가 포함되어 있습니다. 이 값은 null인 경우 규칙이 구문적으로 유효함을 의미합니다. 반환 값이 Null이 아닌 경우 문제를 설명하는 사람이 읽을 수 있는 오류 메시지가 포함됩니다.
편의를 위해 check()
와 동일하게 작동하지만 IOException을 발생시켜 오류 신호를 보내고 성공할 경우 Machine의 addRule()
형식으로 Map
반환하는 compile()
이라는 메서드도 포함되어 있습니다. addRule()
메소드가 기대합니다. Machine 클래스는 이를 내부적으로 사용하므로 이 메서드는 시간을 절약해 줄 수 있습니다.
Ruler는 키를 컴파일할 때 점( .
)을 결합 문자로 사용합니다. 이는 다음 두 규칙을 동일한 내부 표현으로 컴파일한다는 의미입니다.
## has no dots in keys
{ "detail" : { "state" : { "status" : [ "running" ] } } }
## has dots in keys
{ "detail" : { "state.status" : [ "running" ] } }
이는 또한 이러한 규칙이 다음 두 가지 이벤트와 일치함을 의미합니다.
## has no dots in keys
{ "detail" : { "state" : { "status" : "running" } } }
## has dots in keys
{ "detail" : { "state.status" : "running" } }
이 동작은 혼란을 피하기 위해 향후 버전에서 변경될 수 있으므로 이에 의존해서는 안 됩니다.
여러 규칙을 머신으로 컴파일하고 JSON 문자열로 제공되는 이벤트를 일치시켜 Ruler의 성능을 측정합니다.
정확히 일치, 접두사 일치, 접미사 일치, 같음 무시 대소문자 일치, 와일드카드 일치, 숫자 일치 및 기타 일치 항목 5개에 대해 평균 크기가 약 900바이트인 213,068개의 JSON 이벤트를 처리하는 벤치마크입니다. 규칙을 적용하고 일치 항목을 계산하여 2019 MacBook에서 다음을 생성합니다.
다음을 제외하고 이벤트는 220K/초 이상으로 처리됩니다.
다음은 처리 규칙 및 이벤트에 대한 몇 가지 제안 사항입니다.
성능 고려 사항에서 Ruler는 아래 항목에 민감하므로 이벤트 및 규칙의 스키마를 디자인할 때 다음과 같은 몇 가지 제안 사항을 제안합니다.
자세한 내용은 기여를 참조하세요.
이 프로젝트는 Apache-2.0 라이선스에 따라 라이선스가 부여됩니다. 자세한 내용은 라이센스를 참조하세요.