2017-09-11 8 views
0

하루 중 매 시간마다 센서 값을 집계하고 싶습니다. 시간 정보는 이벤트 스트림의 시간 소인에서 가져옵니다. 이를 위해, 나는 네 EPL 문을 만든 : 첫 번째 문은 sensorId 컨텍스트를 사용하여 60 분이 넘는 값을 집계하는 동안 과도한 메모리 사용량이 발생했습니다.

  • 두 번째 문을 감지하여 이벤트를 분할 문맥을 선언

    1. 을 때의 이벤트 스트림의 시간 - 중 - 일 변경 특정 센서를 검색하고 해당 이벤트가 발생할 때 이벤트를 보냅니다.
    2. 세 번째 명령문은 sensorId 및 hourOfDay로 이벤트를 분할하는 컨텍스트 선언입니다. 컨텍스트의 수명은 두 번째 명령문에 의해 게시 된 이벤트에 의해 제어됩니다.
    3. 마지막 문은 문 # 3에서 작성된 컨텍스트를 사용하고 센서 값에 대한 합계를 계산합니다.

    약 2 ~ 6 초마다 약 300 개의 센서에서 이벤트가 수신됩니다. 나는 8 GB의 힙 크기를 가진 자바 애플리케이션에 임베디드 된 ESPER 6.1.0을 가지고있다. 약 15 분 후에 가비지 콜렉션이 과부하되어 응용 프로그램을 사용할 수 없도록하는 메모리 부족이 있습니다. 마지막 EPL 문을 제거하면 응용 프로그램이 정상적으로 다시 작동합니다.

    나는이 동작에 다소 당황 스럽다. 컨텍스트가 사용될 때 esper는 메모리에 이벤트를 축적하지 않을 것이라고 생각했습니다. 내가 메모리 소비가 O (n)이보다는 O (n 개 *의 t),되도록 (예를 들어 합계, 평균) 간단한 집계를 수행 어떻게 가 EPL을 사용 :

    그래서 여기 내 질문 n은 센서의 수이고 t은 시간 창의 길이입니까?

    여기에 제 EPL 선언문이 있습니다.

    문 1

    create context ctxPartitionById partition by sensorId from SensorEvent 
    

    문 2

    context ctxPartitionById 
    INSERT INTO HourChanged 
    SELECT 
        E.sensorId as sensorId, 
        prev(1, E.occurredAtHour) AS lastHour, 
        E.occurredAtHour AS currentHour 
    FROM SensorEvent#length(2) E 
    WHERE E.occurredAtHour != prev(1, E.occurredAtHour) 
    

    명세서 3

    create context ctxPartitionByIdAndHour 
        context PartitionedByKeys 
        partition by 
         sensorId, currentHour from HourChanged, 
         sensorId, occurredAtHour from SensorEvent, 
        context InitiateAndTerm 
        initiated by HourChanged as e1 
        terminated by HourChanged(sensorId=e1.sensorId and lastHour=e1.currentHour) 
    

    문 4

    context ctxPartitionByIdAndHour 
    SELECT 
        E.sensorId, 
        E.occurredAtHour, 
        SUM(E.value) AS sensorValueSum 
    FROM SensorEvent E 
    output last when terminated 
    

    sensorIdComparable을 구현하는 Java 클래스의 인스턴스입니다.

    occurredAtHourjava.util.Date입니다. 이 값은 시간으로 반올림 한 타임 스탬프입니다.

    valuedouble입니다.

  • 답변

    0

    이 문제를 해결합니다.

    이 특별한 힌트가없는 한, 에스페어는 output last이 사용될 때 분명히 메모리에 이벤트를 유지합니다. 자세한 내용은 5.7.3. Runtime Considerations을 참조하십시오.

    0

    키순 컨텍스트는 파티션을 잊지 않습니다. 그래서 당신은 "sensorId, currentHour from HourChanged, sensorId, sensorsEvent에서 발생한 이벤트"에서 파티션을 만들고, 키잉 컨텍스트 (상단)에서 파티션 키는 엔진이 당신이 항상 다음 HourChanged 이벤트를 찾고 있다고 생각하기 때문에 계속 머물러 있습니다. 같은 열쇠.즉, "sensorId"와 "currentHour"의 가능한 모든 조합을 엔진이 기억하고 있음을 의미합니다. 그래서 이것은 당신이 원하는 것이 아닐 수도 있습니다. 이를위한 팁은 솔루션 패턴 페이지에 있습니다.

    문 4의 경우 출력 속도 제한으로 인해 엔진이 종료 될 때 기본적으로 엔진이 출력을 계산하므로 이벤트가 메모리에 남아있게 할 수 있습니다. select 절이 이벤트 속성을 선택하는 방법에 유의하십시오. 이벤트 속성을 선택하면 실제 이벤트에서 가져옵니다. 대신이 쿼리를 완전히 집계 된 쿼리로 만들 수 있으므로 모든 이벤트를 유지할 이유가 없습니다.

    context ctxPartitionByIdAndHour 
    SELECT last(E.sensorId), last(E.occurredAtHour), SUM(E.value) AS sensorValueSum 
    FROM SensorEvent E 
    output last when terminated 
    

    솔루션 패턴에서와 같이 할 수 있습니다. 마지막 4 번째 EPL 문 @Hint('enable_outputlimit_opt') 추가 http://espertech.com/esper/solution_patterns.php#absence-11 http://espertech.com/esper/solution_patterns.php#semantic-window-2

    +0

    http://espertech.com/esper/faq_esper.php#keep_in_memory – user650839

    +0

    정보를 제공해 주셔서 감사합니다. 핵심 컨텍스트가 문제를 일으킬 것이라는 점은 맞지만 응용 프로그램이 약 15 분 내에 메모리가 부족하기 때문에 다소 문제가 있습니다. 범인 인 출력 비율 제한에 대해서도 정확합니다. 힙 덤프를 분석하면 대부분의 메모리가 com.espertech.esper.epl.view.OutputProcessViewConditionDefault 인스턴스에 의해 유지되고 있음을 알 수 있습니다. 그러나 제안 된대로 완전히 통합되도록 마지막 문을 수정 한 후에도 문제가 남아 있습니다. '출력 마지막'을 사용하는 경우 (주문하지 않고) 어떤 이유로 이벤트를 유지해야합니까? –

    +0

    나는 실제 진술이 약간 다르다는 점을 지적해야한다. 특히 마지막 EPL 문은 유틸리티 클래스의 함수를 호출하여 맵에있는 이벤트 속성에 액세스합니다. –