객체지향의 사실과 오해 3 ~ 4장

Book Review|2019. 11. 5. 18:12
객체지향의 사실과 오해
국내도서
저자 : 조영호
출판 : 위키북스 2015.06.17
상세보기

3. 타입과 추상화

추상화는 어떤 내용을 명확하게 이해하기 위해 특정 절차나 물체를 의도적으로 생략하거나 감춤으로써 복잡도를 극복하는 방법이다. 그 방법으로 사물간의 차이점을 빼고 공통점을 일반화하여 단순하게 만들고 불필요한 세부사항을 제거하여 단순화 하는 것이다. 즉 복잡성을 이해하기 쉬운 수준으로 단순화하는 것이다.

 

이런 추상화 개념을 이용해서 객체지향에 대입해서 생각해보자.

 

그룹화

각 객체는 명확한 경계를 가지고 서로 구별할 수 있는 구체적인 사람이나 사물을 말한다.

여러 객체에서 공통적인 요소를 뽑아서 그룹화 하면 복잡성을 효과적으로 감소 시킬 수 있다. 예를 들어 토끼, 강아지 등을 동물이라는 공통의 그룹으로 묶고 사과, 딸기 등을 과일이라는 공통의 그룹으로 묶으면 차이점을 빼고 공통점만을 취해 단순화 할 수 있는 추상화의 일종이다.

 

객체지향에서 객체 개개별로 구별하면 좋지만 그렇기에는 너무 이해하기 어려워지기 때문에 공통적인 특성을 뽑아서 하나로 묶는데 이를 묶기위한 공통적인 기반을 개념(concept)라고 한다. 이런 개념을 이용해서 객체를 여러 그룹으로 분류(classification) 할 수 있다. 이렇게 분류가 된 객체를 그룹의 일원이 되었다고 하여 인스턴스(instance)라고 한다.

 

객체 분류의 개념

그럼 객체에서 그룹으로 분류하기 위해 사용되는 개념은 symbol (이름이나 명칭), intension (개념의 정의), extension (개념에 속한 객체들의 집합) 3가지의 관점을 가지고 있다.

 

토끼라는 객체는 동물이라는 개념의 symbol을 사용하였고 4개의 다리와 척추동물이라는 intension을 사용하였고 같이 소속된 돼지나 강아지들을 보면서 extension을 확인하였다. 이로써 토끼는 동물이라는 그룹으로 분류될 수 있게 되었다.

 

객체 분류의 단점

잘못된 객체 분류를 통해 그룹에 이상한 객체가 소속되면 유지보수가 어렵고 변화에 대처하기가 어려워진다.

위의 내용을 종합해보면 객체를 분류하는 건 공통의 요소를 뽑아서 일반화하고 단순화하여 복잡성을 극복하는 작업이다.

 

 

타입

타입은 개념(concept)와 동일한 의미로써 공통점을 기반으로 객체를 묶기위한 틀이다. 객체에서 가장 중요한건 어떠한 행동을 하느냐가 가장 중요하고 그에 따라 타입이 결정된다. 내부에서 표현하는 방식이 서로 다르더라도 행동이 같다면 둘의 타입은 같을 수 있다.

Animal animal1 = new Dog(); 
Animal animal2 = new Cat(); 

animal1.eat(); 
animal2.eat();

위 두개의 객체의 내부 행동은 다르지만 먹는다는 행동이 같기에 같은 타입을 가질 수 있다. 이를 다형성이라고 한다. 이를 통해서 외부의 행동만 제공하고 내부적으로 상세 내용을 숨기는 캡슐화 원칙을 수행 가능하다.

 

이처럼 객체에 타입을 지정할 때는 데이터가 아니라 행동에 따라서 지정 해야 하는 책임 주도 설계를 해야 한다.

 

일반화/특수화 (supertype/subtype)

객체 타입에는 일반적으로 포함되는 타입과 특수한 타입 두 가지로 나뉜다. 강아지로 예를 들어보면 강아지가 짖는건 일반적인 강아지 타입의 특징이다. 하지만 훈련된 애완견의 경우 일반 강아지와 다른 행동이 가능하다. 여기서 강아지라는 특징은 일반적인 것이고 애완견은 특수화된 타입을 의미한다. 여기서 알 수 있듯이 특수화와 일반화의 차이는 행동을 통해서 기반 된다. 특수화된 타입은 일반화 타입의 특징을 포함하고 있으며 일반적인 특징보다 더 적은 모집군을 가지고 있다.

 

이를 슈퍼타입, 서브타입이라고도 하는데 서브타입은 슈퍼티입의 행위에 추가적으로 특수한 행위를 추가한 것이기 때문에 슈퍼타입의 행동은 서브 타입에게 자동으로 상속된다.

 

3장 결론

  • 타입을 통해서 객체를 분류하는데 이 타입은 객체의 행동을 통해서 정해진다. 이렇게 분류한 타입을 이용하여 클래스를 이용하여 프로그램화 한다.

  • 추상화는 객체의 특징을 보고 일반화/특수화하여 불필요한 부분을 제거하고 단순하게 만들어서 분류하는 것이다.

 

4. 역할, 책임, 협력

객체지향에서 협력은 가장 중요한 프레임이다. 협력에 초점을 맞춰서 설계를 하게 되면 저절로 객체들의 행동이 드러나고 그에따라 상태가 결정된다. 객체의 모양을 빚는 것은 객체가 참여하는 협력으로 어떤 협력에 참여하는지가 객체에 필요한 행동을 결정하고, 필요한 행동이 객체의 상태를 결정한다.

 

책임

객체들간의 협력에서 각 객체가 적절한 행동을 해줄 책임을 가지고 있다. 책임은 객체지향의 중요한 재료로써 눙숙한 프로그램 설계는 객체에게 적절하게 책임을 부여해주는 것을 의미한다.

 

이런 책임을 분류하는 기준은 외부에 제공해줄 수 있는 정보와 외부에 제공해 줄 수 있는 서비스에 대한 정의이다. 이런 책임을 바탕으로 객체지향에서 객체는 어떤 객체에 요청 메시지에 따라 어떤 책임 행동을 해줄 수 있는지 결정하는 것이 포인트이다.

 

역할

역할은 객체지향에서 재사용이 가능하고 유연한 설계를 가지는데 중요한 구성요소이다. 동일한 역할을 동일한 책임을 수행할 수 있다는 뜻이다. 또한 동일한 역할을 하는 객체를 추상화하여 유연성을 가지게 하고 재사용성과 단순하게 객체지향을 설계할 수 있다.

 

이 처럼 역할이 추상화되면 상황에 따라 여러 객체를 대체하면서 사용할 수 있어 유연성이 증가한다.

 

협력에 따라 흐르는 객체의 책임

- 설계 시 객체들 사이에 주고받을 요청과 응답의 흐름을 깔끔하게 만들고 (협력 설계) 그 객체들이 협력에 참여하여 자신의 역할을 책임있게 수행해야 한다.

- 즉 객체간의 관계를 먼저 만들고 그 다음 역할과 책임을 설계하라.

 

 

출처 : 객체지향의 사실과 오해 (조영호)

댓글()

Elasticsearch node 종류와 기본 설정 옵션

Elasticsearch의 노드 

Elasticsearch의 인스턴스를 시작하는 동시에 노드도 같이 시작된다. 노드들을 연결해놓은 것을 클러스터라고 한다.

만약 하나의 엘라스틱 서치 노드만을 실행시킨 경우도 하나의 노드를 가진 클러스터라고 한다. 

클러스터안에서 모든 노드는 HTTP와 Transport 트래픽을 기본적으로 다룬다. Transport 레이어는 오로지 노드들과 Java TransportClient와의 통신에만 사용된다. Http 레이어는 오직 외부 Rest Cliente들과 통신할 때 사용된다.

모든 노드는 클러스터 안에서 서로 다른 노드들에 대하여 알고 있고 client에 요청을 적적한 노드로 향하게 조절해준다. 기본적으로 노드는 master-eligible, data, ingest, machine learning이 존대한다.

 

Elasticsearch의 노드 종류

Master-eligible 노드

- node.master를 true로 지정하며 클러스터의 컨트롤을 통해 마스터 노드로 선택될 자격을 가지게 된다.

- 마스터 노드는 클러스터에서 인덱스를 만들고 지우는 행위, 클러스터에서 노드들을 트래킹하고 각각의 노드를 샤드를 할당할건지 결정한다.

- Masger Eligible Node등에서 마스터 노드는 마스터 설출 프로세스를 통해 선출된다.

(https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-discovery.html)

- 마스터 노드는 데이터 노드처럼 데이터와 폴더에 접근 권한이 있어야 한다. 노드가 재시작 하는 사이에도 클러스터 상태가 유지되어야 하기 때문에 접근이 가능해야 한다.

- 데이터를 인덱싱하고 찾고 하는 작업은 CPU, Memory, I/O 자원을 많이 사용하기 때문에 큰 규모에서는 data node와 master node를 구별한다.

- 마스터 노드도 Coordinating Node 처럼 데이터를 routing하고 모으고 하는 작업이 가능하지만 이는 마스터 노드가 하는 주 목적이 아니다. 안정적인 마스터 노드를 운영하기 위해서는 자기 일만 딱 하게 해주는 것이 좋다.

- 마스터 노드로 노드를 지정하기 위한 기본 설정 값은 다음과 같다.

node.master: true 
node.data: false 
node.ingest: false 
node.ml: false 
xpack.ml.enabled: true 
cluster.remote.connect: false

 

Data 노드

- node.data가 true로 지정된 노드는 데이터를 가지고 있을 수 있고 CRUD, 검색, aggregation 등의 데이터와 관련된 작업이 가능하다.

- 데이터 노드는 인덱싱 된 Document를 포함하고 있는 샤드를 관리한다.

- 데이터 노드는 데이터를 직접적으로 다루기 때문에 리소스 자원이 많이 필요하다.

- 데이터 노드로 노드를 지정하기 위한 기본 설정 값은 다음과 같다.

node.master: false 
node.data: true 
node.ingest: false 
node.ml: false 
cluster.remote.connect: false

 

Ingest 노드 

- node.ingest가 true로 지정된 노드가 Document가 인덱싱 되기 전에 변형되고 풍성하게 하기 위해서 Document를 ingest pipeline으로 적용할 수 있다.

- ingetst node는 pre processing 파이프라인을 실행하고 하나 또는 하나 이상의 ingest processor들을 모으는 작업을 한다.

- ingest를 로드하는건 무겁기 때문에 데이터나 마스터 노드에서는 node.ingest를 false로 지정하는 것이 좋다.

- 많은 리소스를 잡아먹기 때문에 ingest node는 별도로 지정하는 것이 좋다.

- ingest 노드로 노드를 지정하기 위한 기본 설정 값은 다음과 같다.

node.master: false 
node.data: false 
node.ingest: true 
node.ml: false 
cluster.remote.connect: false

 

Machine Learning 노드

- xpack.ml이 true로 지정되어 있고 node.ml이 true로 설정되어 있는 노드는 기본적으로 엘라스틱서치에서 분배하는 행위를 한다.

- 만약 머신러닝 특징을 사용하고 싶으면 적어도 클러스터 내에 하나의 머신러닝 노드가 있어야 한다.

 

Coordinating 노드

- 검색 요청과 bulk indexing과 같은 요청들은 다른 노드들의 있는 데이터를 많이 다룬다.

- 데이터가 흩어져 있는 경우 데이터가 있는 노드로 향하게 조정해준다. 각각의 데이터 노드는 요청을 자체적으로 처리하고 그것의 값을 Coordinating 노드에 전달해준다. 그럼 Coordinating 노드는 이를 모아서 하나의 데이터 형태로 정제하여 반환한다.

- 각각의 노드는 Coordinating node가 될 수 있다. 대신 node.master, node.data, node.integer가 false로 되어 있어야 한다.

- 또한 데이터를 모으고 조작하고 하는 작업이 많기 때문에 Coordinating 노드는 메모리랑 CPU에 대한 자원이 많아야 한다. 그렇기 때문에 오직 요청을 라우팅하고 검색 구절을 조절하고, bulk indexing 분배작업을 하는 노드로만 사용하는 게 좋다.

- Coordinating node는 본질적으로 로드 밸런싱 같은 역할을 한다.

- Coordinating node로 지정하기 위한 설정은 다음과 같다.

node.master: false 
node.data: false 
node.ingest: false 
node.ml: false 
cluster.remote.connect: false

 

Node Data Path Setting

path.data

- 모든 데이터와 master-eligible 노드는 샤드 그리고 인덱스, 클러스터 메타데이터가 저장되어 있는 데이터 디렉토리를 접근한다.

- path.data는 기본적으로 $ES_HOME/data로 지정되어 있지만 elasticsearch.yml을 통해서 바꿀 수 있다.

댓글()

[번역] shared message queues와 publish-subscribe 방식에 Custom Group 방식을 더한 Kafka 소개

web/kafka|2019. 2. 14. 09:27

전통적으로 메시지 모델은 Shared Message Queue, Publish-subscribe로 구분된다. 두 가지 모델 모두 그들만에 pros and cons를 보유하고 있다. 하지만 이 두개의 모두 최초 디자인 제한 때문에 큰 데이터를 다루기에는 부족했다. Apache Kafka는 두 모델 중 publish-subscribe 메시징 모델을 구현한 모델로 부족했던 부분을 수정하고 실시간 분석을 위한 스트리밍 데이터를 처리할 수 있도록 가능해졌다. kafka는 LinkedIn에서 2010년에 방대한 데이터 처리를 위해서 개발되었다. Apache Kafka는 전통적인 메시징 모델이 달성하지 못한 격차를 해소했다. Kafka는 두 모델의 개념을 구현하여 단점을 극복하고 동시에 두 가지 방법론을 모두 통합 할 수있는 유연성을 제공한다.


Shared Message Queues
Shared Message Queues 메시지 큐는 producer에서 single consumer에게 스트리밍 데이터를 전송할 수 있다. 큐에 저장된 메시지는 한번만 읽기가 가능하고 하나의 consumer만 읽을 수 있다. subscribers는 메시지를 큐의 끝에서 메시지를 읽어서 가지고 온다. Queueing 시스템은 성공적으로 읽혀진 메시지를 큐에서 제거한다.

약점
한번 읽고 지워지는 SharedMessage Queue는 같은 도메인에 속해 있고 event-driving programming을 하는 명령어와 같은 메시지에서 적합하다. 만약 많은 consumer들이 shared queue에 접근을 하게 된다면 해당 컨슈머들은 logical domain이 같아야 하고 같은 기능을 수행해야 한다. 그렇기 때무에 shared queue는 single domain 소비로 제한된다.

Publish-Subscribe System
publish-subscribe모델은 여러 publisher가 발행이 가능하고 여러 subscriber가 구독이 가능하게 설계되어 있다. 그래서 모든 메시지는 토픽을 구독하는 모든 subscriber들에게 전송이 가능하도록 되어있다.

약점
subscriber로부터 publisher의 logical 결합이 loosely-coupled 되어 있지만 scale은 한정적이다. 각각의 subscriber는 모든 파티션으로 부터 메시지를 접근하기 위해서는 모든 파티션을 접근해야한다. 그러므로 전통적인 pub-sub 모델은 작은 네트워크에서 동작하도록 되어있다.

또한 subscriber와 publisher에 디커플링이 메시지의 신뢰도를 낮추는 영향을 준다. 모든 메시지가 모든 subscriber들에게 전송되기 때문에 메시지가 다른 subscirber에게 전송되는 경우 subscriber들 사이에 sync를 맞추는게 실질적으로 어렵다.


그럼 어떻게 Kafka는 두 모델을 결합했을까?
kafka는 shared message queue 시스템과 pub-sub 모델의 장점을 가지고 만들어졌다. 그 성공은 두개의 컨셉을 기준으로 만들어졌다.
  • consumer group 사용
  • broker들로 부터 메시지 리텐션

consumer가 그룹에 소속되고 topic을 구독할 때 오직 하나의 consumer만 그룹내에서 토픽의 메시지를 읽는다. 그리고 메시지는 broker 내부 토픽에서 사라지지 않고 보유되는데 이는 shared message queue 시스템과 다른점이다.

여러 consumer group은 같은 토픽에서 값을 읽을 수 있으며, 또한 서로 다른 logical application domain에서 다른 시간데에서도 읽을 수 있다. 그러므로 kafka는 같은 consumer group에 속한 consumer들의 높은 확정성을 제공하고 동시에 독립적인 애플리케이션들이 동작할 수 있는 이점이 있다.

Consumer Group
consumer group은 kafka가 message queue와 pub-sub 모델들의 이점을을 가질 수 있도록하는 유연성을 제공한다. 같은 그룹에 속한 consumer들은 group id를 공유한다. 이 consumer들은 토픽의 파티션을 공장하게 나눈다. 이 각각의 파티션들은 오직 그룹내에 하나의 consumer에서만 소비된다.

kafka Consumer Groups
만약 같은 그룹에 모든 consumer가 들어있으면 kafka 모델은 전통적인 message queue처럼 동작한다. 왜냐면 각각의 메시지가 하나의 consumer에게만 발행되는 부분이 같기 때문이다. 각각의 파티션은 거의 그룹내에 하나의 consumer와 연결된다.

여러 consumer group가 존재할 때 데이터 소비 모델은 전형적인 pub-sub 모델을 따른다. 메시지는 모든 consumer group에게 전송된다.

만약 하나의 consumer만 들어있는 그룹이 있으면 그 consumer가 모든 파티션을 담당한다.

이상적으로 topic의 파티션 수와 consumer group에 consumer 수가 맞으면 최적으로 효율을 가진다. 만약 consumer가 파티션보다 많으면 consumer들이 idle상태에 빠지게 되므로 자원 낭비가 발생된다. 만약 partition이 consumer보다 많은 경우 consumer들은 여러 파티션에서 값을 있는데 이는 각 파티션에서 읽는 값이 서로 순서가 맞지 않게 읽게 되기 때문에 문제의 소지가 있다. kafka는 파티션 사이에서 메시지의 순서를 보장하지 않는다. 그러므로 kafka는 오직 하나의 consumer가 하나의 파티션의 내용을 구독할 때만 순서가 보장된다. 메시지는 또한 processing중에 그룹화된 키를 통해서 정렬될 수 있다.

kafka는 offset commit과 form을 사용하여 브로커에서 구독 그룹으로 메시지가 전송되었느지 보증한다. 파티션은 consumer그룹내에 오직 하나 또는 하나 이상의 관계를 consumer와 맺을 수 있기 때문에 메시지 중복을 피하기 위해서 한번에 그룹내에서 한번에 하나의 그룹에게만 메시지를 전송한다.

Reblancing
consumer그룹이 scales up & down을 하기 때문에 동작중인 consumer들은 파티선을 그 들 사이에서 쪼갠다. Reblancing은 consumer와 broker의 충돌 또는 topic이나 partition 추가로 인해 파티션과 consumer의 소유권이 변경되면서 진행된다. 이 매커니즘을 이용하여 안전하게 시스템으로 부터 consumer의 추가와 제거가 가능하다.
-> 요약하면 consumer에 문제가 발생하면 다른 consumer가 파티션의 메시지를 받는다 이런 것 같다.

kafka가 시작되면서 브로커는 consumer의 RegisterConsumer 요청을 수신한 consumer group의 하위 집합에 대한 코디네이터로 표시되고 소유해야할 파티션 목록이 포함된 RegisterConsumer Response를 반환한다. 또한 코디네이터는 컨슈머가 살아있거나 죽었는지 체크하고 결함을 찾기위해 동작을 시작한다. 또한 세션이 끊어지기 전에 consumer가 코디네이터 브로커에게 heartbeat 신호 전송에 실패하면 코디네이터는 해당 consumer를 dead로 표시하고 rebalance를 실행한다. 세션 타임아웃 시간은 session.timeout.ms 속성에서 설정할 수 있다. 예를들어 그룹 A의 C2가 실패 했으면 C1그리고 C3가 짧게 자기들의 파티션에서의 메시지 소비를 정지하고 파티션들은 C1과 C2에 대해서 reassian된다. C2 consumer는 잃게 되지만 rebalancing 프로세스가 실행되고 파티션이 그룹내에 다른 consumer들에게 재 할당된다. GroupB는 Group A의 이런 현상이 전혀 영향을 주지 않는다.

결론
shared message queue는 메시지 프로세스내에서 scale을 허용한다 하지만 싱글 도메인에서만 사용이 가능하다. pub-sub 모델은 consumer들에게 브로드캐스팅을 지원하지만 scale이 제한된다. kafka는 shared message queue에서 scale을 가져왔고 pub-sub 아키텍쳐를 consumer gorup를 구현함으로써 단점을 보안하여 재 구현하여 가져왔다. consumer group를 구현함으로써 scale과 멀티 도메인을 사용할 수 있게 되었다. 그리고 kafka에 rebalacing을 통해서 그룹내에서 문제 발생시 문제를 해결할 수 있다.

원문
https://blog.cloudera.com/blog/2018/05/scalability-of-kafka-messaging-using-consumer-groups/




댓글()

Nginx, Apache 그리고 node.js 성능 관련 잡다한 정리

web/node.js|2019. 2. 7. 23:20

Nginx과 Apache 비교


 

 Nginx

Apache 

특징 

- Nginx는 싱글 스레드 Event driven 방식

- 미리 설정된 worker 프로세스 안에서 요청이 들어올 때 마다 요청을 분배하여 worker에게 역할을 분배

- 기존에 정해놓은 리소스를 사용하기 때문에 CPU, Memory 등의 자원 사용률이 낮음

- 요청이 올 때마다 쓰레드를 생성하여 할당한다. 작업이 많아질 경우 많은 쓰레드할당이 필요하다. 그리고 쓰레드들이 작업을 진행 할 때마다  CPU를 사용하려 하기 때문에 문맥교환이 자주 발생된다. 

차이점 

 - Apache에 경우 Blocking 방식으로 Network, DB 등 별도의 동작이 진행 될 때 Block되지만 Nginx는 Non-blocking 방식을 지원함


Non-blocking, Event Loop 방식의 Node.js


- Event Loop 방식은 요청이 오면 무조건 이벤트 핸들러에게 요청을 넘김. 그 것이 처리되면 완료되었다고 연락이온다. 그래서 Single Thread Non-blocking 방식이 가능

- Single Thread이기 때문에 Multi thread의 자원에 대한 크리티컬 섹션에 대한 문제가 발생하지 않음.

- Node.js는 Single Thread를 사용하기 때문에 CPU에 문맥교환이 발생하지 않아서 Multi Thread를 지원하는 프레임워크보다 무조건 빠를다고 하지만 그렇지는 않다. Node.js에서 요청은 비동기를 지원하지만 내부적으로 Event를 처리할 때는 libio의 Thread Pool에 의해 동작하기 때문에 I/O 작업이 많을 때는 Multi Thread 방식이 유리하다.(Node.js는 메시지 처리와 같이 I/O가 적은 작업이 어울림.) 

- Single Thread이기 때문에 CPU를 많이 잡아먹는 연산일 경우 다른 작업도 모두 느려지기 때문에 연산이 오래걸리는 작업에는 어울리지 않음.

- Node.js에 특성상 오류가 발생하면 프로그램이 죽어버림

- Single Thread Async를 지원하고 있지만 네트워크, DB와 같은 I/O가 발생할 때는 libio의 Thread Pool에 작업이 전달되고 완료되면 EventQueue에 CallBack 함수에 전달된다.


=> 결론 

Single Thread를 사용. 비동기지만 I/O 발생 시 내부적으로 비동기처럼 동작하기 위해 쓰레드 풀을 사용하여 진행한다. 그래서 요청이 많을 경우 문맥교환이 일어나는 Multi Thread보다 오히려 성능이 나쁠 수 있다.


Nginx와 Node.js

Nginx와 Node.js를 사용할 때 성능적으로 도움이 되는 설정을 정리했다.


Port Range

- Nginx에서 Node.js에 요청을 보낼 때는 2개의 TCP 소켓이 필요하다.(2개의 포트가 필요) 그래서 가용 가능한 포트가 적을 경우에 요청을 받지 못하는 문제가 발생한다. 그래서 상황에 따라서 sysctl의 net.ipv4.ip_local_port_range를 사용하여 설정한다.


Time Wait

- Time wait는 커넥션이 종료 되었으나 할당된 연결이 아직 release가 되지 않은 자원이다. 그래서 요청이 와도 자원을 사용할 수 없어서 문제가 발생할 수 있어서 이를 사용할 수있게 해줘야 한다. sysctl의 net.ipv4.tcp_tw_reuse값을 1로 변경해줘야 한다.


Time Wait 시간

- Time Wait 자원을 사용할 수 있는 자원으로 변경되는 시간을 줄여서 빠르게 사용할 수 있게 해주는 것이 좋다. sysctl의 net.ipv4.tcp_fin.timeout값을 줄이면 된다.


Context Switch 

Node.js에서 사용중인 CPU 코어가 다른 프로세스에서 사용되지 않도록하면 성능 향상에 도움이 된다. 여러 프로세스에서 하나의 코어를 같이 사용할 수 있다. 각각의 프로세스는 돌아가면서 코어 스케줄대로 이용한다. 이 경우 문맥교환이 많이 발생하여 CPU 부하가 증가한다. 그렇기 때문에 node에서 사용하는 CPU 코어는 다른 업무를 못하게하여 서로 코어를 잡아먹으려 하는 문맥교환을 줄여야한다.

※ Context switch

- 문맥 교환(Context Switch)이란 하나의 프로세스가 CPU를 사용 중인 상태에서 다른 프로세스가 CPU를 사용하도록 하기 위해, 이전의 프로세스의 상태(문맥)를 보관하고 새로운 프로세스의 상태를 적재하는 작업을 말한다.


현재 Connection 상태를 확인하는 명령어

netstat -tan | awk '{print $6}' | sort | uniq -c


Nginx에서 Upstream이란?

Nginx 설정에서 Upstream이 있다. 여기서 Upstream은 순차적으로 서비스를 처리하기 위해 사용되는 서버를 의미한다. Nginx에서 내장된 Upstream 모듈은 설정된 서버들의 부하분산, 속도 개선을 담당한다. 일반적으로 설정된 서버의 Upstream은 라운드 로빈 방식으로 진행된다.


※ 라운드 로빈

라운드 로빈 스케줄링(Round Robin Scheduling, RR)은 시분할 시스템을 위해 설계된 선점형 스케줄링의 하나로서, 프로세스들 사이에 우선순위를 두지 않고, 순서대로 시간단위(Time Quantum)로 CPU를 할당하는 방식의 CPU 스케줄링 알고리즘이다.


댓글()

Kafka 요약 정리

web/kafka|2019. 1. 24. 21:42

Topic

- 메시지는 Topic에 분류된다.


Partition

- Topic은 partition으로 구분된다.

- 파티션에 쌓이는 데이터는 로그라고 부르고 각 파티션에 나눠서 저장된다.


Topic이 파티션으로 나뉘는 이유

- Topic 내부에 파티션이 없을경우 메시지를 보내는 대상이 많아질경우 append 속도가 버거워진다. 

- 병렬로 분산저장하고자 Partition 개념 생성

- 한번 생성한 파티션은 운영중에 줄일 수 없기 때문에 설계시 조심


Consumer

- Topic에 있는 데이터를 읽는 대상


Consumer Group

- Consumer를 여러개 묶어놓은 것.


Consumer Group이 필요한 이유.

- 소비를 진행 하던 Consumer가 죽어버릴 경우를 Rebalance 상황이라고 하는데 이럴경우 파티션 재 조정을 통해서 다른 컨슈머가 이어서 진행한다.

- 파티션이 많아서 데이터를 처리해야하는 경우 Consumer Group내에서 파티션을 나눠서 읽을 수 있기에 속도가 좋다.

- 무조건 늘리는게 아니라 적절하게 속도 조절 필요.(읽는 속도가 더 빠르다면 굳이 늘리지말고 Consumer 하나당 담당하는 Partition을 늘려라.)

- 그리고 핵심적인 이유가 만약 그룹이 없이 Consumer 여러개가 같은 topic에서 데이터를 읽을 때 offset이 공유가 되기 때문에 마지막 Consumer가 읽어간 부분부터 읽게되기 때문에 데이터가 신뢰도가 부족해진다. 하지만 Group을 사용하게 되면 Group마다 offset을 다르게 쓰기 때문에 그럴 염려가 없다.


Broker

- 카프카 서버


Zookeeper

- kafka를 실행시키기고 관리하는 주최


Replication

- kafka 서버를 여러개 띄울 경우 하나만 leader고 나머지는 follower가 됨.

- 리더가 읽고 쓰고를 주관하고 나머지는 대기 (리더가 죽으면 나머지들 중 하나가 리더가 됨)


파티션이 구분되면 메시지 순서는 보장될까?

- 파티션이 생기고 Consumer Group에서 Topic에 데이터를 읽으면 순서가 보장되지 않는다. Round robin 처럼 파티션을 돌아다니면서 데이터를 읽는 구조로 기본적으로 되어있지만 한쪽 파티션이 느려지거나 문제가 생기면 정상적인 파티션을 먼저 읽게된다. 그래서 중요한건 같은 파티션 내에서는 순서가 보장되지만 같은 토픽내에 다른 파티션들끼리는 순서가 보장되지 않는다.



공부는 했지만 정리가 되지 않았던걸 정리해봤다. 이제는 이해가 잘되는 것 같다.

댓글()

Kafka 정리

web/kafka|2018. 12. 30. 23:18

카프카는 분산형 스트리밍 플랫폼으로써 다음으로 정의할 수 있다.

  • 메시지 큐와 유사하게 스트림을 publish하고 subscribe 하는 방식이다.
  • fault-tolerant 지속 방식으로 레코드들의 스트림들을 저장한다.


용도

  • 시스템이나 어플리케이션에서 발생한 실시간 스트리밍 데이터를 안정적으로 데이터 파이라인 구축할 때
  • 데이터 스트림을 전송하거나 처리해야할 때 사용


구성

  • 하나이상에 서버에 여러 cluster로 구성되어 있다.
  • topic이라는 카테고리로 레코드 스트림들을 저장한다.
  • 각각의 레코드들은 key, value, timestamp로 구성되어 있다.


핵심 API

Producer API

  • 하나 또는 그 이상의 카프카 topic을 데이터 스트림에 발행할 수 있도록 해주는 API

Consumer API

  • 어플리케이션이 하나 또는 하나이상의 topic을 구독할 수 있게 해주고 그것으로 부터 생산된 스트림을 처리하게 해준다.

Streams API

  • 어플리케이션을 효과적으로 input stream에서 output stream으로 데이터가 잘 전송될 수 있도록 하나 또는 하나 이상의 topic으로 부터 들어온 input stream을 소비하고 하나 또는 하나 이상의 topic을 생산하도록 하는 stream processor로서 행동하게 해준다.

Connector API

  • 어플리케이션 또는 데이터 시스템에서 존재하는 kafka topic에 재사용 가능한 producer 또는 consumer로 구성되고 동작할 수 있도록 제공해주는 API


Topics and Logs
kafka에서는 제공하는 핵심 추상화인 Topic에 대해 정리해보자.

topic은 category 또는 publised된 레코드의 feed name이다. 카프카에서 topic은 항상 멀티 subscriber를 가지고 있고 데이터를 구독하는 consumer를 0 또는 1 그리고 더 많이 소유할 수 있다.

각각의 토픽에 대해 kafka 클러스터는 다음과 같은 파티션 로그를 유지한다.

각각의 파티션은 연속적으로 추가되는 정렬된 시퀀스화되어 있는 커밋로그이다. 파티션 안에서 recode는 파티션 내에서 고유하게 식별이 가능하도록 offset이라는 연속적인 id를 가지고 있다.

kafka에서 크러스터는 소비가 되기전까지 데이터가 보관되고 만약 데이터 보관 정책에 따라서 몇일까지만 보관하도록 지정할 수 있다. 소비가된 레코드는 공간에서 제거된다.



또한 offset을 기준으로 사용자가 데이터를 접근하여 읽을 수 있다.


Producers
producers는 topic을 선택하여 데이터를 publish할 수 있다. producers는 topic내에서 어떤 파티션에 레코드를 publish 할건지 선택해야한다.
이 선택 방식은 load balance를 맞추기 위해서 라운드 로빈 방식으로 수행되거나 일부 의미적 파티션 함수에 따라 수행될 수도 있다.(파티셔닝으로 선택되기도 한다.)

Consumers
Consumers는 Consumers group 이름을 가지고있다. topic이 published된 각각의 레코드는 각각의 구독 consuber group내에 하나의 컨슈머에게 전달된다. Consumer 인스턴스는 각각의 프로세서로 구성되거나 각각의 서버에서 구성되어 있을 수 있다.

만약의 모든 consumer가 모두 같은 consumer group에 있으면 레코드는 효과적으로 각각의 consumer들에게 적절하게 부하분산 처리가 될 것이다.

만약 모든 consumer가 서로 다른 consumer 그룹에 포함되는 각 레코드가 모든 consumer processor에 브로드 캐스팅을 하게 된다. (즉 다시 말하자면 구독하고자 하는 레코드가 있는 consumer는 하나의 group으로 지정하는게 좋다.)



위에 그림은 2개의 Consumer group에서 4개의 파티션으로 구성된 kafka cluster를 구독하고 있다. A Consumer 그룹은 2개 B는 4개의 Consumer를 보유하고 있다.

각각의 그룹은 다수의 Consumer로 구성되어 있다. 이는 하나의 consumer가 죽으면 각 파티션은 다른 consumer 인스턴스에 값을 전달한다. 


Messaging System으로써 Kafka

일반적으로 이런 메시지 방식을 지원하는 rabbitMQ와 같음 메시지 큐가 존재한다. 하지만 이런 전통적인 Message Queue와 kafka가 무엇이 다른지 알아보자.

일반적인 메시징은 Queuing와 publish-subscribe 두 개의 모델을 가지고 있다. Queue에서는 소비자의 pool은 서버로 부터 읽어들이고 각각의 레코드는 그 둘 중 하나로 저장된다. publish-subscribe 모델에서 레코드는 모든 고객에게 brodecast된다. 이 두 가지 모델은 각각 강점과 약점이 존재한다. Queuing의 강점은 여러 consumer 인스턴스에서 데이터 처리를 나눌 수 있으므로 나눌 수 있다. 하지만 Queing은 Multi subscribe 방식이 아니기 때문에 하나의 프로세스에서 읽으면 다른 프로세스는 읽을 수 없게 데이터가 사라진다. publish-subscribe는 다중 프로세스에게 브로드캐스트하는 장점이 있지만 모든 메시지가 모든 구독자에게 전달 되기 때문에 scaling을 조절할 방법이 없다. (어차피 모든 구독자에게 전달되기 때문에)

반면에 kafka에 있는 consumer group 개념은 두 가지 개념을 생성한다. queue와 비슷하게 consumer group은 그룹내에 각 consumer들에게 처리를 분산할 수 있다. 그래서 별도의 consumer를 지정할 필요없이 자동으로 값을 분산할 수 있다. publish-subscribe 방식과 비슷하게 모든 그룹에게 kafka는 메시지를 브로드 캐스트 할 수 있다.

그리고 일반적인 Message system에서 queue는 서버에서 순서대로 레코드를 보유하고 있으며 다중 consumer가 소비하려할 경우 서버에 저장된 순서대로 레코드를 전달한다. 하지만 서버가 순서대로 보내도 다중 Consumer에게 비동기로 값을 전달하기 때문에 결국 순서 보장이 되지 않는다. (이를 Consumer를 하나로 지정하여 문제를 해결할 수 있지만 병렬처리가 안되는 단점 발생)

하지만 카프카는 파티션 개념을 가짐으로써 consumer 프로세스 풀에 대한 순서를 보장하고 부하분산도 보장한다. 방식은 Consumer 그룹 내에서 topic내에 특정 파티션을 하나의 Consumer에게 특정하여 subscribe하게 전달한다.. 그러면 Consumer가 해당 파티션의 유일한 독자가 되기 때문에 문제에 소지가 없어지고 순서대로 순서가 보장된다. 파티션이 많아지면 많은 Consumer를 하나의 그룹으로 지정함으로써 부하분산을 처리한다. 하지만 Consumer group은 파티션보다 더 많은 수의 consumer를 보유 할 수 없다.

-> 정리하자면 기존의 메시지 큐는 하나의 큐에서 멀티 consumer가 있을 경우에 서로 데이터를 순서보장없이 가져가서 처리하기 때문에 순서가 보장되어야 하는 동작에 문제가 생긴다. 하지만 카프카에서는 소비자 그룹을 지정하고 각 그룹에서 특정 소비자는 특정 파티션의 내용만 받아서 처리하기 때문에 순서가 보장된다. 결국에 핵심은 kafka에는 consumer group이라는 개념이 도입되어서 더 안정적인 부하분산과 데이터처리가 가능해진 것 같다. 그리고 하나더 브로드 캐스팅 할 때도 모든 데이터가 다 consumer들에게 전달되는 일반 메시지 큐와 달리 브로드캐스팅시 각 그룹내에 consumer에게 값을 나눠서 전달하고 하나로 처리하는 kafka가 더 좋다는 이야기인 것 같다.


다음 시간에는 카프카를 spring reactive를 사용해서 한번 메시지를 전달하고 받아보고 처리하는 동작을 만들어보자.

참고 : https://kafka.apache.org/intro


댓글()
  1. 대니 2018.12.30 23:19 댓글주소  수정/삭제  댓글쓰기

    대단하세요

마이크로서비스 역량 모델

web/마이크로서비스|2018. 10. 23. 11:42
마이크로 서비스 구현에 필요한 역량은 상황에 따라 다를 수 밖에 없다. 그래서 마이크로서비스 설계 시 필요한 역량 모델에 대해 정리해보자.  

마이크로서비스의 역량 모델은 크게 4 개의 영역으로 분류할 수 있다. 
  • 핵심역량
  • 지원역량
  • 인프라스트럭처 역량
  • 프로세스 및 통제 역량




1. 핵심역량 (Core capabilities)
- 핵심 역량은 하나의 마이크로서비스 안에 패키징 되는 컴포넌트이다. 이곳에서 서비스 리스너, 실행 라이브러리, 서비스 구현 코드, 서비스 API와 종단점이 들어있다.


※ 서비스 리스너와 라이브러리
  • 서비스 리스너는 마이크로 서비스로 들어오는 서비스 요청을 접수하는 종단점 리스너이다.
  • 주로 사용 되는 리스너는 AMQP나 JMS 같은 메시지 리스너가 주로 사용된다.

※ 저장 기능
  • 데이터를 저장 하는 RDBMS나 NoSQL에 저장 할 수 있다.

※  서비스 구현 (Service implementation)
  • 실제로 사용 되는 비즈니스 로직 으로 자바, 스칼라 등등으로 어떤 언어로도 구현할 수 있다.

※ 서비스 종단점 (end-point)
  • 외부의 서비스 소비자가 서비스에게 요청을 전송할 수 있게 외부에 공개한 API를 말한다.
  • 종단점은 동기 또는 비동기일 수 있다. 비 동기인 경우에는 AMQP, 스프링 클라우드 스트림과 같은 메시지 리스너를 통해 요청을 받아서 백엔드에 있는 RabbitMq나 다른 메시징 서버 또는 제로엠큐 같은 다른 방식의 메시징 구현체를 통해 처리한다.




2. 인프라스트럭처 역량
- 성공적인 배포를 위해 인프라스트럭처 역량도 필요하다,

※ 클라우드
  • 인프라스트럭처를 프로비저닝하는 데 오랜시간이 소요되는 전통적인 데이터 센터 환경에서는 마이크로서비스를 구현하는데 어렵다.
  • 많은 애플리케이션이 분리되어 실행되는 마이크로서비스에경우 별도의 데이터 센터에서 관리하면 너무 관리 비용이 크기 때문에 클라우드 인프라스트럭처가 더 나은 선택이다.
  • 클라우드 방식의 인프라스트럭처는 컨테이너나 가상머신을 탄력적으로 늘리고 줄이는 오토스케일링이 가능하다.
 
※ 컨테이너 런타임
  • 다수의 마이크로서비스를 대용량 물리 장비에 배포하는 것은 비용이 많이 든다. 그래서 물리적인 장비만으로는 자동화된 장애 대응성을 갖추기 어렵다.

※ 컨테이너 오케스트레이션
  • 컨테이너나 가상머신의 수가 많으면 자동으로 유지 관리하기 어렵다.
  • 컨테이너 오케스트레이션 도구는 컨테이너 런타임 위에서 일관성 있는 운영환경을 제공하며 가용한 자원을 여러 컨테이너에 분배한다. 대표적 도구로 아파치 메소스, 쿠버네티스 등이 컨테이너 오케스트레이션 도구로서 널리 사용된다.
  • 수작업으로 하면 번거롭고 오류 발생도 높다. 그래서 컨테이너 오케스트레이션 도구를 사용하면 애플리케이션 배포, 트래픽 제어, 인스턴스 복제, 무 중단 업그레이드를 자동으로 수행할 수 있다.
  • 컨테이너 오케스트레이션 도구는 가용성확보와 데이터 센터에 걸친 배포 인스턴스 최소 사용 등의 관리 활동에 도움이 된다.




3. 지원역량 (Supporting Capabilities)
지원 역량은 마이크로서비스와 직접적으로 연결되지는 않지만 대규모 마이크로 서비스 배포에 필수적이다.

※ 서비스 게이트웨이
  • 서비스 게이트웨이 또는 API 게이트 웨이는 서비스 종단점에서 프록시 역할과 종단점을 조합하는 역할을 담당한다.
  • 대표적으로는 스프링 클라우드 zual, Mashery, Apigee, Kong, WSO2, 3scale 등 다양한 제품들이 있다.

※ 소프트웨어 정의 로드 밸런서
  • 로드 밸런서는 유동적으로 변형되는 상황에서 적절하게 대처가 가능하도록 설계가 되어야 한다.
  • ribbon, Eureka, zuul등을 사용해서 지능적인 소프트웨어 정의 로드 밸런서를 구현할 수 있다.
  • 컨테이너 오케스트레이션 도구에서도 로드밸런싱 기능을 잘 사용할 수 있도록 제공하는 방법이 있다.

※ 중앙 집중형 로그 관리
  • 로그파일은 분석과 디버깅에 중요한 정보를 제공한다. 로그는 각각의 인스턴스 디스크에 저장된다. 그래서 분산된 로그를 통합 관리해야한다.
  • 그렇게 하기 위해서 마이크로서비스에서 각 애플리케이션에서 발생한 로그를 중앙 로그 저장소에 저장되도록 해야한다.

※ 보안서비스
  • 분산 마이크로서비스 생태계에서 서비스 인증이나 토큰 서비스 같은 서비스 보안을 담당하는 중앙의 서버를 만들어야 한다.
  • 스프링 부트 OAUTH를 사용해서 인증 방식을 추가할 수 있다.

※ 서비스 환경설정
  • 마이크로 서비스를 사용하여 각자 애플리케이션이 배포 되면서 모든 애플리케이션 관련 설정을 따로따로 관리하기가 쉽지 않다.
  • 그래서 각 환경 설정을 외부화 해야한다. 이런 환경설정 관리 서버로 스프링 클라우드 config 서버, Archaius를 사용할 수 있다.
  • 소규모 마이크로 서비스같이 동적으로 설정을 변경할 필요가 없는 경우 Spring Boot의 프로퍼티로 해도 된다.





4. 프로세스 및 통제역량
프로세스 및 통제 역량은 마이크로 서비스 구현에 필요한 프로세스, 도구, 가이드라인등을 의미한다.


 데브옵스
  • 애자일 개발, 지속적 통합, 자동화 QA, 자동화된 전달 파이프라인, 자동배포, 자동화 인프라스트럭처 프로비저닝 등을 도입 해야 한다.

 자동화 도구
  • 테스트 자동과 자동 배포 등과 같은 자동화 도구 관리를 잘해야 한다.

 컨테이너 레지스트리
  • 마이크로서비스의 버전관리를 위한 artifactory 저장소를 사용한다.

 마이크로서비스 문서화
  • 마이크로서비스에서 개발된 종단점에 대한 정보를 어떻게 보여줄것인지를 보관하는 문서를 가지고 있어야한다.
  • 효과적인 마이크로 서비스 문서는 웹 브라우저에서 접근할 수 있어야 하며, API를 쉽게 탐색하고, 샘플 테스트가 가능해야 한다.
  • 가장 많이 사용하는 라이브러리는 Swagger를 사용한다.

 참조 아키텍처 및 라이브러리
  • 마이크로 서비스는 여러 애플리케이션이 독릭접으로 구성되는데 라이브러리를 가지각색으로 사용하면 문제가 된다.
  • 그래서 중앙에서 공용으로 사용할 수 있는 공용 라이브러리를 만들어서 사용해야 한다.


댓글()

TCP/IP 정의와 전송과정 정리

IT 지식/네트워크|2018. 5. 27. 21:45

TCP/IP(Transmission Control Protocol / Internet Protocol)?

네트워크와 네트워크를 연결하기 위한 포로토콜.

여러 개의 네트웍을 연결해서 데이터를 서로 주고 받기위해서로 상호연결하기위한 프로토콜이다.

 

데이터가 생성 되면 각각의 계층에서는 각각의 헤더(Header)를 붙이게 된다헤더라는 것은 각 계층에서 해야 할 일들을 정의한 오버헤드(Overhead)라고 할 수 있는데각 계층을 지나면서 각 계층에서 해야 할 일을 헤더에 붙이는 작업을 데이터 캡슐화(Data Encapsulation)라고 한다.


역 다중화(Demultiplexing) : 수신 측 입장에서 데이터 생성과정.

 


전송과정


1. 데이터링크 계층

패킷을 전달하는 물리적 인터페이스와 관련된 하드웨어를 제어하는 기능을 수행한다.

- TCP/IP 상에서 데이터 전송을 위해서는 IP주소(32bit)와 MAC주소(48bit) 주소필요.

(.수진 측 모두 필요)

물리적의 IP주소를 사용하여 목적지 MAC주소를 획득하는 프로토콜.


2. 네트워크 계층

네트워크 상의 패킷 이동의 제어(패킷을 전달하고 경로를 선택)기능을 수행하는 프로토콜이다. (라우팅 기능 수행)

사용자의 데이터를 패킷 형태로 전송하는 기능을 수행하는 비 연결형 프로토콜이다전송 요청을 라우터에 보내면라우터가 알아서 해당 목적지에 요청을 한다. (라우팅 기능)

 

3. 전송계층

두 호스트 간에 종단 간 연결을 맺고 데이터를 전달할 수 있는 기능을 수행.

 

4. 응용계층

- TCP/IP 프로토콜의 이용하는 서비스

댓글()