참고 사이트

 

 

Spring Integration Overview

스프링 인티그레이션의 핵심 개념과 메인 컴포넌트 소개

godekdls.github.io

 

Main Component

스프링 인테그레이션은 파이프 필터 모델로 작성되며 구성은 “파이프”, “필터”, “메시지”로 이루어져 있다.


Message

스프링 인테그레이션에서 사용되는 데이터를 의미하며 사용하는 데이터를 감싼 래퍼(wrapper)이다.
즉 Message와 같은 wrapper형식으로 사용한다.


Message Channel(Pipe)

메세지 채널은 Pipe의 역할을 하며 Message를 Filter로 전달하는 역할을 한다.
메시지를 전달하는 프로듀서 채널, 메시지를 받아가는 컨슈머 채널이 ****분리되어 있어 채널간 인터셉터 등을 사용 할 수 있다.

Message Channel Interface

  • MessageChannel
  • PollableChannel
  • SubscribeChannel

Message Channel Impliment

위의 메시지 인터페이스를 구현한 구연체들이 존재한다.

  • publishSubscribeChannel: 전달받은 Message를 자신을 구독한 모든 Handler에게 전달한다.
  • QueueChannel: Point to Point로 해당 채널의 컨슈머가 여럿 있더라도 하나의 컨슈머에 전달한다.
  • 큐가 가득차면 send 메소드를 호출 시 sender를 블록킹한다*.
  • 큐가 비어있다면 recevie호출이 블록킹 된다.*
  • PriorityChannel: 큐 채널은 First -In-First-Out을 따르지만 PriorityChannel은 메시지마다 우선순위를 부여할 수 있다.
  • RendezvousChannel: receive를 호출 하기 전까지 sender를 블록한다.
  • DirectChannel: point-to-pint로 동작하며 PollableChannel을 구현한것이 아닌 SubscribeChannel을 구현하였기에 메시지를 직접 Handdlrt에 전달한다.
    Poller방식이 아니기 때무에 스레드를 스케줄링 하지 않아 오버헤드가 없기 때문에 Spring Integration의 디폴트 채널이다.
    구독하고 있는 MessageHandler를 호출하는 일을 메시지 디스페처에 위임한다.
  • ExcutorChannel: DirectChannel과 같지만 MessageHandler를 호출하는 디스패치 수행을 TastExcutor에게 위임한다는 것이다.
  • FlusMessageChannel: 리액티브 구독자가 온맨드로 컨슘해갈 수 있도록 전달받은 메시지를 변경하는 채널

MessageEndpoint(Filter)

Filter는 메시지를 컨슘하는 모든 구성요소를 말한다.

Message Transformer

메시지의 내용 및 구성요소를 변환하고 수정한 메시지를 반환하는 일을 한다.
Ex) Byte를 String으로 변환한다던지.

MessageFilter

메시지 필터는 해당 메시지를 다른 채널로 전달할지 말지를 결정한다. 필터에서는 간단한 boolean 테스트 메소드가 있으면 된다. Ex) header 값에 따른 전달 여부 판단.

MessageRouter

메시지 라우터는 해당 메시지를 여러 채널중 분기처리를 할 때 사용된다.
Ex) 콜 시작 메시지 → callStartChannel, 콜 종료 메시지 → callEndChannel

Spliter

입력 받은 메시지를 여러 메시지로 분할하는 역할을 담당하며 일반적으로 “복합”페이로드를 세분화하여 여러 메시지로 나누는데 사용한다.

Aggregator

Spliter와 반대로 여러 메시지를 하나의 메시지로 통합할 때 사용된다.

ServiceActivator

서비스 인스턴스를 메시지 시스템에 연결하기 위한 범용 엔드포인트이다. 입력 채널을 반드시 구성해야하며 반환할 수 있는 경우 출력 체널도 지정할 수 있다.

ChannelAdeptor

채널 어뎁터는 메시지 채널을 다른 시스템이나 전송 구성요소에 연결해주는 엔드포인트다. 어뎁터는 인바운드와 아웃바운드로 구성된다.


간단한 예제

https://github.com/Kmmanki/spring_integration_study_1

 

GitHub - Kmmanki/spring_integration_study_1

Contribute to Kmmanki/spring_integration_study_1 development by creating an account on GitHub.

github.com

해당 예제는 pythonSender - Spring Integration - pythonReceiver 로 구성되어 있으며

 

python과 Integration은 TCP 소켓으로 연결한다.

python sender에서 1 이라는 입력을 주면 spring integration에서 1 > 2 메시지를 만들어 pythonReceiver 전달하고 pythonReceiver 는 전달 받은 메시지에 > 3을 붙여 1 > 2 > 3을 만들어 integration으로 reply한다. integration은 전달받은 1 > 2 > 3에 > 4를 붙여 1 > 2 > 3 > 4를 다시 reply하여 sender로 전송한다.

 

예제코드 도식화

 

 

 

'기타 > 기타의 기타' 카테고리의 다른 글

자격증 정리  (0) 2023.12.28
c++ 포인터와 referense를 이용한 두 변수 값 바꾸기  (1) 2023.12.26
JVM Runtime Data Area  (1) 2023.12.23

정보처리기사


Tensorflow Developer


SQLD


 

// Online C++ compiler to run C++ program online
#include <iostream>
using namespace std;

template <typename T>
void pointerSwitch(T* a, T* b){
    // a의 주소 b의 주소를 받음음
    T tmp = *a; // 입력 받은 인수가 주소이기 때문에 값으로 변환

    *a = *b;
    *b = tmp;
}

template <typename T>
void referenceSwitch(T& a, T& b) {
    T tmp = a;
    a = b;
    b = tmp;
}

int main() {
    int a = 10;
    int b = 20;
    cout << *&a;

    cout << "a는" << a << "\n";
    cout << "b는" << b << "\n";    
    cout << "pointer switch \n" ;    
    
    pointerSwitch(&a, &b);
    
    cout << "a는" << a << "\n";
    cout << "b는" << b << "\n";  
    cout << "reference switch \n" ;
    
    referenceSwitch(a, b);
    
    cout << "a는" << a << "\n";
    cout << "b는" << b << "\n"; 
    return 0;
}

 

 

10a는10
b는20
pointer switch 
a는20
b는10
reference switch 
a는10
b는20

'기타 > 기타의 기타' 카테고리의 다른 글

Spring Integration 컴포넌트 간단정리  (0) 2024.03.25
자격증 정리  (0) 2023.12.28
JVM Runtime Data Area  (1) 2023.12.23

JVM Runtime Data Area는 자바 애플리케이션 실행을 윟나 메모리 영역으로 아래와 같이 나뉜다.

 

  • Register
  • JVM Stack
  • Native Method Stack
  • Method Area
  • Heap

Registert, JVM Stack, Native Method는 각 Thread가 개별적으로 소유한 공간이나, Method Area, Heap은 모든 Thread가 공유하므로 JVM이 기동시 생성된다.

 


Register

CPU 내의 레지스터는 데이터를 신속하게 저장하여 사용하는 공간으로 data, address, status등으로 구성 되어 있다.

JVM 내에도 PC register, optop, frame, vars 등으로  구분되어 있다.

 

PC register는 현재 메서드가 실행할 다음 bytecode의 address를 가지고 있다. 다만 자바 메서드가아닌 Native 메서드를 처리한다면 PC register의 값은 undifined이다.(비 자바 언어를 위한 별도의 Native Method Stack이 존재하기 때문)

 

Stack 영역을 관리하는 3개 Register는 각각 다음 영역에 대한 포인터를 가지고 있다.

  • optop Register -> Operand Stack
  • vars Register -> Local Variable
  • frame Register -> Execution Environment

JVM Stack

각 Thread는 고유의 JVM Stack을 가지고 있다. Stack은 Frame을 여러장 쌓아놓은 구조이며 1개의 Frame은 1개의 Method에 대응한다.

  • JVM Stack의 단위 = Thread 단위
  • Stack Frame = Method의 단위

JVM Stack은 그 이름과 같이 후입선출(LIFO)방식이기 때문에 메서드를 호출하면 Stack의 최상단에 새로운 Frame이 놓인다. 그리고 메소드의 수행이 끝나면 최상단의 Frame은 제거된다. Frame의 내부 구조는 다음과 같다.

 

  • Operand Stack
  • Local Variable
  • Execution Environment

Operand Stack 

연소나 과정의 피연산자가 push, pop되는 공간이다.

int i1 = 1;
int i2 = 2;
int i3 = i1 + i2;

 

  1. int 1을 Operand Stack에 push 한다.
  2. Operand의 int 1을 Local Vairable Slot에 pop 한다.
  3. int 2를 Operand Stack에 Push한다.
  4. Operand의 int 2를 Local Variable Slot에 pop 한다.
  5. Local Variable의 int 1을 Operand에 Push한다.
  6. Local Variable의 int 2을 Operand에 Push한다.
  7. Operand의 두 int를 add 한다.
  8. Operand의 int 3을 Local Vairable Slot에 pop한다.

Operand Stack의 각 slot 크기는 32bit 이므로 long, duble과 같은 타입은 2개의 slot을 사용한다.

 

Local Variavble 내에는 메서드의 Parameter와 Local variable이 존재한다.

boolean, byte, char, long, short 등은 1개의 slot, float, double은 2개의 슬롯을 사용한다. 다만 Object, String은 크기를 알 수 없는 객체의 경우 Heap에 저장되고 Local variable에  reference만 저장되며 1개의 slot을 사용한다. Primitive Type은 Heap 영역을 거치지 않기 때문에 상대적으로 성능이 좋을 수 있다.

 

 JVM Stack 처리중 발생 할 수 있는 오류는 StackOverFlowError와 OutOfMemoryError 등이 있다. 

 

  • StackOverFlowError: 사용 가능한 Stack의 크기보다 많은 메소드 생성 및 호출
  • OutOfMemoryError : 충분하지 않은 메모리;로 Stack의 생성 실패

Native Method Stack

자바 애필리케이션 내 C언어 등 타 언어 코드를 실행 할 수 있다 이 때는 JVM Stack이 아닌 Native Mehtod Stack에서 Native Method를 처리한다.


Method Area

ClassLoader Reference, Runtime Constant Pool, Field Inforamtion, Method Information, Mehtod Code 등을 저장하고 있다. Runtime Constrant Pool은 클래스타 인터페이스의 Constant 뿐만 아니라 Type, Method, Field에 대한 reference 정보를 가지고 있다.

 


Heap

Heap 영역은 Tomcat 등 WAS 운영 관리에 가장 밀접한 영역이다.

 

Heap 영역 구조

New Generation, Old Generation

  • New Generation: 막 생성된 객체, Old Generation으로 이동 하지 않은 비교적 새로운 객체의 공간
    • Eden: New Generation의 객체중에서도 가장 최근에 생성된 객체를 위한 공간이며 Minor GC 발생 시 이 객체들은 Survivor 영역으로 이동한다.
    • Survivor 1,2 : Eden에서 살아남은 객체의 공간으로 MinorGC 발생시마다 1 < -> 2 로 이동한다.
  • Old Generation: 오랜 시간 살아있는 객체의 공간

이러한 메모리 공간의 크기는 JVM의 커맨드 옵션으로 설정할 수 있다.

  • 전체 매모리 설정: -Xms(초기값), -Xmx(최대값)
  • New Generation과 Old Generation의 비율: -XX:NewRatio
  • New Generation 내부의 Eden, Survivor의 비율: -XX:SurvivorRatio

 


Permanent Generation

New Generation과 Old는 객체들을 위한 공간이라면 Permanent Generation은 클래스 정보를 저장하는 공간이다. 간혹 애플리케이션 내부에서 동적으로 많은 클래스를 생성하는 경우가 있는데 이럴 때 Permanent Generation이 부족 해질 수 있다.

 

  •  Permanent Generation 크기설정 :-XX:PermSize(초기값), -XX:MaxPermSize(최대값) 

 Permanent Generation의 확장 시 Full GC가 발생하기 때문에 가급적 두 값을 동일하게 설저 하는 것이 좋다.

 

Metaspace

자바 1.8부터는  Permanent Generation가 사라지고 Metasapce로 변경되었다.

  • Metaspace의 크기 설정: -XX:MetaspaceSize, -XX:MaxMetaspaceSize

Garbvage Collection

GC는 메모리 객체중 Garbage 객체를 식별, 정리하여 여유 메모리를 확보한다.

 

그러나 GC 메커니즘이 문제를 유발하기도 한다. Full GC수행 중 모든 애필리케이션 처리가 중단 되기 때문이다. 이를 Stop-The-World(STW)라고 부른다. STW의 시간은 Heap의 크기에 비례한다. 따라서 Heap을 많이 할당하는 것이 반드시 좋은 것만이 아니다 적잘한 메모리의 할당과 GC 정책이 필요하다.

 

Seral GC

가장 기본적인 GC로 자바 1.4에서는 Serial GC를 기본으로 사용하였다. 반명 1.5이후로는 호스트 파워를 분석하여 어떠한 GC 방식을 사용할지 결정한다 명시적으로 -XX:+UseSerialGC 옵션을 통해 Serial GC를 사용 할 수 있다.

 

Serail GC는 하나의 Thread가 GC 작업을 처리한. 머신의 processor가 복수 개 라고 해도 하나의 Thread가 처리한다. 또한 New Generation은 Generational 알고리즘, Old Generation은 Mark-compact 알고리즘을 처리한다.

 

Parallel Old GC

하나의 Thread가 처리하는 단점을 보안하기 위해 Parallel Old GC가 등장 했으며 Parallel Compacting 알고리즘을 사용한다.

 

Parallel GC의 Thread의 수는 반드시 CPU의 코어 수를 고려하여 설정해야한다. 기본적으로는 1:1이다.

 

G1 GC

메모리 공간을 Region이라는 영역으로 나누어 사용하는데 New Generation, Old 모두 Region을 사용한다.

 


오류의 유형

 

OOM Java heap space: Heap 영역내 객체생성을 위한 충분한메모리가 없을 때

OOM Requested array size exceed VM limit: Heap 현재 메모리 공간에서 처리 할 수 없을 만큼 큰 배열을 생성하는 경우

OOM ParmGen space: 너무 많은 클래스 정보를 로드 할 때 발생

OOM unable to create new native thread: OOM의 원인이 메모리가 아닌 OS 자원에 있을 가능성이 크다

 


OOM의 원인

할당한 Heap메모리가 절대적으로 적기 때문이다. 이때 -XmX옵션을 통해 최대 Heap을 늘려야 한다. 단 이때 GC로그를 보면 Heap의 최적의 값을 찾아야한다.

 

대용량의 데이터 조회/입력으로 인하여 OOM이 발생하는 경우도 많으며 이는 DB 처리 후 수만~ 수십만의 데이터를 패치한 후 Heap영역의 Collection 객체에 로드하게 되는데 주로 조회 리포트, 엑셀 다운로드 작업을하는 관리자 시스템이서 발생한다. 대용량업무를 처리하는 별도의 인스턴스를 분리하는 것이 바람직 하다.

 

메모리 누수 또한 원인이 된다. 주로 Heap 덤프를 분석하거나 APM도구를 통해 찾아 낼 수 있다. 한편 JNI(JAVA Native Interface)를 통해 Native 코드를 호출하는 과정에서 Native 영역에서 누수가 발생할 수 있다.


모니터링 도구 

  • jstat: Heap: DK가 기본으로 제공하는 텍스트 기반 모니터링 도구
  • jmap: Heap을 모니터링 할 수 있으며 Heap영역의 정보를 덤프파일로 생성할 수 있다.
  • jhat: jmap의 dump를 통해 생성한 Heap 덤프 파일을 분석후 html 형태로 제공하는 도구

+ Recent posts