마이크로서비스란?

  1. 별도의 프로세스에서 실행
  2. HTTP API 같은 가벼운 매커니즘으로 통신하는 작은 애플리케이션
  3. 여러개의 분리되어있는 서비스들은 각자의 비즈니스 기능을 담당함
  4. 자동화 된 절차에 따라 서비스들은 독립적으로 배포됨
  5. 각 서비스는 서로 다른 프로그래밍 언어로 개발되어도 괜찮고, 서로 다른 데이터 저장소를 사용할 수 있음

(왼)우리가 사용하는 넷플릭스, (우) 넷플릭스는 수많은 서비스들의 조합으로 비즈니스 기능을 수행

마이크로서비스 관련 유명한 글 : https://martinfowler.com/articles/microservices.html

 

Microservices

Defining the microservices architectural style by describing their nine common characteristics

martinfowler.com

 

아마존의 모놀리틱시스템에서 마이크로서비스로 도입할 때 적용 규칙

  1. 모든 팀은 해당 팀의 기능 및 데이터를 Service Interface를 통해서만 노출 해야 한다.
  2. 다른 팀의 기능/데이터를 사용하려면 Network를 통한 Service Interface를 호출해야 한다.
  3. Service Interface 기술을 상관 하지 않겠다.(HTTP, Corba, etc.)
  4. 누구든 이것을 지키지 않으면 해고하겠다.

아마존의 수많은 서비스들의 조합

넷플릭스에서 오픈소스로 개발한 아키텍처 패턴 및 OSS (Netflix OSS)

우리는 해당 시스템을들 이용하여 상대적으로 편하게 마이크로 서비스를 구현하면 됨

 

 

Mediator 패턴 그림

 

Mediator 패턴 개념

여러 객체 간의 통신을 관리하고, 각 객체가 서로 직접 참조하지 않고 중재자를 통해 통신할 수 있게 해주는 디자인 패턴. 통신 시스템에 적용하면, 모듈 간의 복잡한 상호작용을 단순화하고, 시스템의 결합도를 낮출 수 임.

 

Mediator 구성 요소

 

  • Mediator(중재자): 여러 객체 간의 통신을 중재하고 조율하는 객체.
  • Colleague(동료): Mediator를 통해 다른 객체와 상호작용하는 객체.

 

C++ 코드

Mediator 인터페이스 정의

class Colleague;

class Mediator {
public:
    virtual void sendMessage(const std::string &message, Colleague *colleague) = 0;
    virtual void registerColleague(Colleague *colleague) = 0;
};

 

 

Colleage 클래스 정의

class Colleague {
protected:
    Mediator *mediator;
public:
    Colleague(Mediator *m) : mediator(m) {}
    virtual void receiveMessage(const std::string &message) = 0;
};

 

Concrete Mediator 및 Concreate Colleague 구현

#include <vector>
#include <iostream>

class ConcreteMediator : public Mediator {
private:
    std::vector<Colleague*> colleagues;
public:
    void sendMessage(const std::string &message, Colleague *sender) override {
        for (auto colleague : colleagues) {
            if (colleague != sender) {
                colleague->receiveMessage(message);
            }
        }
    }

    void registerColleague(Colleague *colleague) override {
        colleagues.push_back(colleague);
    }
};

class ConcreteColleague : public Colleague {
public:
    ConcreteColleague(Mediator *m) : Colleague(m) {}

    void receiveMessage(const std::string &message) override {
        std::cout << "Colleague received: " << message << std::endl;
    }

    void send(const std::string &message) {
        mediator->sendMessage(message, this);
    }
};

 

사용 예제

int main() {
    ConcreteMediator mediator;

    ConcreteColleague colleague1(&mediator);
    ConcreteColleague colleague2(&mediator);

    mediator.registerColleague(&colleague1);
    mediator.registerColleague(&colleague2);

    colleague1.send("Hello from colleague 1");
    colleague2.send("Hello from colleague 2");

    return 0;
}

'Program > SW Design Patterns' 카테고리의 다른 글

CH8 스테이트 패턴  (0) 2023.12.04
CH7 어댑터&퍼사드 패턴  (0) 2023.03.19
CH6 커맨드 패턴  (0) 2023.03.07
CH5 데코레이터 패턴  (1) 2023.03.05
CH4 팩토리 패턴  (0) 2023.03.04
생각 없이 행할 수 있는 중요한 작업의 수가 늘어남에 따라 문명은 발전한다.
- Alfred North Whitehead

책에서 말한 Progmatic Starter Kit 은 아래 3가지 주제를 다룬다.

  1. 버전 관리
  2. 회귀 테스트
  3. 전체 자동화


1. 버전 관리

tip 89 버전 관리 시스템으로 빌드, 테스트, 릴리즈를 운용하자.

버전 관리 시스템의 커밋, 푸시로 빌드와 테스트, 배포가 시작된다.
빌드 : 클라우드의 컨테이너 위에서 빌드한다.
배포 : 빌드한 릴리즈 파일은 아래 2가지 서버 중 한 곳에 태그를 사용하여 지정한다.

  1. 테스트용 staging 서버
  2. 실제 서비스

key : 빌드 장비, 개발자의 장비에 의존하지 않고 지속적 배포가 가능해야함.
전체 흐름 : 커밋 or 푸시 -> 빌드 -> 배포(staging 서버 or 운용 서버)


2. 회귀 테스트

tip 90 일찍 테스트하고, 자주 테스트하라. 자동으로 테스트하라.
tip 91 모든 테스트가 끝날 때 까지는 코딩이 끝난게 아니다.
tip 92 버그를 심어 놓고 테스트를 테스트하라.
tip 93 코드 커버리지만 올리지 말고 상태 조합을 테스트하라.
tip 94 버그는 한 번만 잡아라.


자동 빌드가 모든 가용한 테스트를 수행한다.
실제 상황과 같은 테스트를 목표로 하는 것이 중요하다.
테스트 종류는 아래 4가지이며, 4가지를 갖춰도 완벽한 테스트를 한 것은 아니다.

  1. 단위 테스트(unit test) : 하나의 모듈을 테스트 (함수, Class)
  2. 통합 테스트(integration test) : 프로젝트를 구성하는 서브 시스템이 다른 서브 시스템들과 제대로 작동하는지 테스트 (시스템 연동 테스트)
  3. 유효성 평가 및 검증(validation and verification) : 사용자들이 필요로 한 것인지, 시스템의 기능적 요구 사항을 충족하는 것인지 확인
  4. 성능 테스트 (performance test) : 예상하는 사용자 수, 접속 수 혹은 초당 트랜잭션 숫자를 수용 하는가? 주기성을 만족 하는가?

한번 버그를 발견 했다면, 해당 버그를 발견하는 테스트 코드를 추가하자.

3. 전체 자동화

tip 95 수작업 절차를 사용하지 말라.

rsync, ssh를 넣은 셸 스크립트 부터 시작해서 Ansible, Puppet, Chef, Salt 처럼 좋은 기능을 갖춘 패키지를 사용하여 시스템을 전체 자동화 하자.
수작업 단계를 단 1개도 넣지 말자.


직접 찾아본 자동화 툴과 특징
1. Github Action(public 무료, private 유료)

가능한 자동화 : 빌드 -> 테스트 -> 배포 파이프라인
특징 :
Workflows, Events, Jobs, Steps, Actions, Runners 등 몇가지 구성 요소를 알고 있어야함.
yaml 파일 사용
컨테이너 기반 동작

2. Jenkins (무료)


가능한 자동화 : 빌드 -> 테스트 -> 배포 파이프라인 자동화
특징 :
Pipeline, Node, Stage, Step 등 몇가지 구성 요소를 알고 있어야함.
Declarative Pipleline 또는 Scripted Pipleline 2가지 방식으로 사용
외부 컴포넌트에 대해 Plugins 기능 제공 (Git Plugin, Pipeline 등…)
Jenkinsfile 파일 사용

3. 그외… AWS CodeBuild, Azure DevOps, Bamboo, Argo CD, 트래비스 CI


내가 사용한다면..?
1. 현재 사용 중인 언어 : C, C++, C#, python
2. 모의기 GUI framework : WPF
3. 사용중인 framework : .NET Framework
3. 주요 OS  : Ubuntu 20.04, Windows 10, 11
4. 사용 중인 컴파일러 : gcc, .NET

opencv 라이브러리를 호스트 시스템에서 크로스 컴파일하여 타깃 시스템에서 사용 할 경우

 

1. 타겟 시스템에서 원하는 opencv 버전을 설치한다. (apt-get install -> make -> install 까지 모두!!)

이유 : 타겟 시스템 (CPU) 에 맞게 컴파일한 opencv lib, include 파일 들을 생성하기 위함

2. 타겟 시스템에서 usr 폴더를 복사한다!

opencv가 설치된 /root/usr/include, /root/usr/lib 등..

이유 : 타겟 시스템에 맞게 컴파일한 opencv 를 가져오기 위함.

 

3. 호스트 PC의 작업 환경의 sysroot 폴더로 복사한다.

-> 예시 : 

폴더 workspace

      -> 파일 main.c

      -> 파일 main.h

      -> 폴더 sysroot 

           -> 폴더 usr

                -> 폴더 bin

                    ...

                -> 폴더 include
                    ...

                -> 폴더 lib

                    ...

                -> 폴더 sbin

                ...

     

4. 크로스 컴파일 명령어

gcc --sysroot=./sysroot -I/usr/local/opencv/include/opencv4 -L/usr/local/opencv/lib -static -lopencv_core -lopencv_imgcodecs -lopencv_highgui -o main ./main.c

 

5. 크로스 컴파일 후 해당 실행파일을 타겟 시스템에서 실행!!

IEEE Std에서의 Architecture 정의

1. 시스템의 환경 (HW, SW, OS, Network, 구동 실환경 등..)

2. 하나 이상의 컴포넌트들 간의 관계 (ICD)

3. 설계와 발전 (확장성, 품질, 생명 주기 등..)

1,2,3을 관리하는 원칙으로 이루어진 시스템 구조

 

Gof(Gang of Four)의 Ralph Johnson 의견

1. IEEE std에서 정의한 Architecture의 정의가 거시적임.

2. 실제 소프트웨어를 개발하는 개발자들의 상식이 소프트웨어 프로젝트를 이끄는데 중요하고, 아키텍쳐에 영향을 끼칠 것임. 

 

전문 개발자들은 정보를 공유함.

 

3. 중요한 것은 프로젝트에 대한 이해도가 개발자들 간에 잘 공유되어야함!!!

4. 결정들은 바꾸기 어렵다! (핵심 기능, 프래그래밍 언어 등..)

5. 올바른 결정은 요구하는 시스템에 대한 정보를 알아야한다.

 

6. 지식을 잘 공유하고, 바꾸기 어려운것 것들을 모두 포괄하여 SW를 설계하기 위해서는

시스템에서 무엇이 핵심인지 알아야한다!!

7. SW 아키텍처는 SW 장인 정신 보다는 경제적 관점을 중요시해야한다.

8. 우리의 SW를 사용하는 고객은 SW 좋은 디자인을 보는 사람은 아님, 친절한 UI, 적은 결함이 중요시 함.(사용자 경험 등..)

9. 그리고 좋은 SW 디자인은 장기간으로 봤을 때 유지비용 시간이 적고, 기능추가에 용이해짐!

10. SW의 퀄리티는 크게 2가지로 나뉨, 외부적 퀄리티, 내부적 퀄리티

 - 외부적 퀄리티 : 직관적인 UI, 적은 버그

 - 내부적 퀄리티 : SW 디자인

11. 디자인이 없는 SW는 기능을 추가 할 수록 시간이 매우 많이 들게 될 것임.

12. 꾸준한 리펙토링과 모듈화를 통해 기능을 분리한 SW를 시간이 지나도 SW 기능 추가가 쉬울 것임.

 

영상 링크 : https://www.youtube.com/watch?v=4E1BHTvhB7Y

제목의 의미

  1. Decision Transformer: Decision Transformer는 강화 학습(RL)을 수행하는 모델임. 이 모델은 트랜스포머(Transformer) 아키텍처를 사용하여 행동을 결정하는 방식에 쓰임.
  2. Reinforcement Learning: 강화 학습은 에이전트가 환경과 상호작용하면서 보상을 최대화하는 행동을 학습하는 기계 학습의 한 분야임.
  3. via Sequence Modeling: 시퀀스 모델링을 통해, Decision Transformer는 RL 문제를 조건부 시퀀스 모델링 문제로 변환함. 이는 과거의 상태와 행동, 그리고 보상을 기반으로 최적의 행동을 예측하는 방식임. 트랜스포머 모델을 사용하여 시퀀스를 예측함으로써 강화 학습을 수행합니다.

Decision Transformer라는 새로운 모델이 시퀀스 모델링을 통해 강화 학습 문제를 해결함.  기존의 가치 함수나 정책 그래디언트를 계산하는 강화 학습 방법 대신, 이 모델은 과거의 데이터와 목표 보상을 기반으로 미래의 행동을 예측 .


 Abstract 정리

  • 논문은 강화 학습(RL)을 시퀀스 모델링 문제로 추상화하는 프레임워크를 소개함.
  • 이를 통해 트랜스포머 아키텍처의 단순성과 확장성을 활용가능함.
  • 논문은 Decision Transformer라는 아키텍처를 제안함.
  • 이 아키텍처는 RL 문제를 조건부 시퀀스 모델링으로 변환함.
  • 기존의 RL 접근 방식과 달리, Decision Transformer는 최적의 행동을 출력하는 데 중점을 둠.
  • 과거의 상태와 행동, 원하는 보상에 따라 미래의 행동을 생성함.
  • 이 모델은 Atari, OpenAI Gym, Key-to-Door 작업에서 최신 model free offline RL 성능과 비슷하거나 좋은 성능을 냄.


 

  • 제안하는 트랜스포머 모델을 이해하기 위해, 방향 그래프에서 최단 경로를 찾는 작업을 강화 학습 문제로 고려함.
  • 최단 경로를 찾는 환경에서 에이전트가 목표 노드에 있을 때 보상은 0이고, 그렇지 않으면 -1입니다.
  • 논문은 GPT 모델을 훈련하여 returns-to-go(미래 보상의 합), 상태 및 행동의 시퀀스에서 다음 토큰을 예측합니다.
    • returns-to-go : 현재 상태에서 goal state로 갔을때의 return 값을 의미함.
  • 전문가 시연 없이 랜덤 워크 데이터로만 훈련합니다.
  • 테스트 시 최적 궤적을 생성하기 위해 최고 가능한 반환값을 생성하는 사전을 추가합니다.
  • 그런 다음, 조건 설정을 통해 해당 행동 시퀀스를 생성합니다.
  • 따라서, 시퀀스 모델링 도구를 사후 반환 정보와 결합하여 동적 프로그래밍 없이 정책 개선을 달성합니다.

의문점 :

1. 최고 가능한 반환값을 생성하는 사전을 추가

2. 조건 설정


 

 



 

 

ChatGTP 적극활용!

제목의 의미 

다중 에이전트 강화 학습(Multi-agent reinforcement learning; MARL)이 일련의 의사결정 문제로 추상화될 수 있으며, 이를 통해 시퀀스 모델링(sequence modeling) 기법을 적용할 수 있다는 의미. 여러 에이전트가 상호작용하는 과정을 시퀀스 데이터로 보고 이를 모델링하는 접근 방식을 강조.

 

Abstract 요약

1. 대규모 시퀀스 모델(GPT 시리즈와 BERT 등)은 자연어 처리, 비전, 최근에는 강화 학습에서 뛰어난 성능과 일반화 능력을 보여줌.

2. 따라서 다중 에이전트 의사결정도 시퀀스 모델링 문제로 추상화하고, 이를 통해 시퀀스 모델링의 발전을 활용할 수 있는 방법에 대해 아이디어를 얻을 수 있음.

3. 이 논문에서는 다중 에이전트 강화 학습(MARL)을 시퀀스 모델링 문제로 효과적으로 변환하는 새로운 아키텍처인 Multi-Agent Transformer (MAT)를 소개함.

4. MAT의 목표는 에이전트들의 관찰 시퀀스를 최적의 행동 시퀀스로 매핑하는 것입니다.

5. MAT의 핵심은 multi-agent advantage decomposition theorem을 활용하여 공동 정책 탐색 문제를 순차적 의사결정 과정으로 변환하는 인코더-디코더 아키텍처입니다.

6. 이를 통해 다중 에이전트 문제에서 선형 시간 복잡성을 가지며, 단조로운 성능 향상 보장을 제공합니다.

7. 기존의 Decision Transformer와 달리 MAT는 환경에서 온라인으로 시행착오를 겪으며 학습합니다.

8. MAT를 검증하기 위해 StarCraftII, Multi-Agent MuJoCo, Dexterous Hands Manipulation, Google Research Football 등에서 실험을 수행하였으며, MAPPO 및 HAPPO와 같은 강력한 기준보다 우수한 성능과 데이터 효율성을 입증했습니다. 또한, MAT는 에이전트 수의 변화와 관계없이 새로운 작업에서 우수한 few-short learner 성능을 보여줍니다.

 

쌈뽕한 내 차

import numpy as np
import matplotlib.pyplot as plt

def newton_method(f, f_prime, x0, tolerance=0.00001, max_iterations=100):
    x_values = [x0]
    iterations = 0

    while True:
        x1 = x0 - f(x0) / f_prime(x0)
        x_values.append(x1)
        iterations += 1

        if abs(x1 - x0) < tolerance or iterations >= max_iterations:
            print(f"iteration complete! {iterations}")
            break

        x0 = x1

    return x_values

# Define the function and its derivative
def function(x):
    return 0.5 * x**2

def derivative(x):
    return x
    
 
# Set initial values
initial_guess = 50

# Run Newton's method
resulting_values = newton_method(function, derivative, initial_guess)

# Plot the convergence process
x_values = np.linspace(-50, 50, 1000)
y_values = function(x_values)

plt.plot(x_values, y_values, label='object Function f(x) = 0.5 * x^2')
plt.scatter(resulting_values, function(np.array(resulting_values)), color='red', label='Convergence Points')
plt.title("Newton's Method in Convex Function")
plt.xlabel('x')
plt.ylabel('f(x)')
plt.legend()
plt.show()

 

import random
import matplotlib.pyplot as plt

def convex_function(x):
    return 0.5 * x**2  # 예제로 사용할 convex 함수: f(x) = 0.5 * x^2

def convex_function_diff(x):
    return x

def plot_convergence(maxiterations = 50, threshold = 0.1):
    x_values = np.linspace(-50, 50, 1000)
    y_values = convex_function(x_values)

    plt.plot(x_values, y_values, label='object Function f(x) = 0.5 * x^2')
    plt.title('Convergence of a Convex Function')
    plt.xlabel('x')
    plt.ylabel('f(x)')

    # 초기값 설정
    initial_x = random.randint(-50, 50)
    learning_rate = 0.1
    iterations = 50

    new_x = initial_x
    x_values_history = []
    for i in range(maxiterations):
        x_values_history.append(new_x)
        gradient = convex_function_diff(new_x)  # f'(x) = x for this example
        next_x = new_x - learning_rate * gradient

        if (abs(new_x - next_x) < threshold):
            print(f"iteration complete! {i}")
            break
        new_x = next_x
        

    plt.scatter(x_values_history, convex_function(np.array(x_values_history)), c='red', label='Convergence Points')
    plt.legend()
    plt.show()

# 수렴 과정 plotting
plot_convergence(50,0.00001)

+ Recent posts