programming/MSA

Serverelss Framework

yhsim98 2022. 9. 19. 03:32

Serverless

  • 클라우드 제공업체가 클라우드 인프라와 애플리케이션 스케일링을 모두 관리

  • 표준 서비스 인프라(laaS) 클라우드 컴퓨팅 모델에서 사용자는 용량 단위를 사전에 구매하게 된다.

  • 상시 가동 중인 서버 구성 요소에 대한 비용을 지불하고, 수요가 많을 때 스케일 업이나 다운하는 것 역시 사용자의 책임. 애플리케이션을 구동하기 위해 필요한 클라우드 인프라는 애플리케이션이 사용되지 않을 때도 활성화된 상태이다.

  • 반면, 서버리스 아키텍처에서는 애플리케이션이 필요한 경우에만 시작.

  • 이벤트가 구동을 위한 애플리케이션 코드를 트리커하면 퍼블릭 클라우드 공급업체가 신속하게 해당 코드에 대한 리소스를 할당. 코드 실행이 종료되면 비용도 청구되지 않는다.

  • 비용과 효율성 외에도, 서버리스는 애플리케이션 스케일링 및 서버 프로비저닝(과 같은 부분에서도 개발자의 부담을 덜어준다.

  • 비동기식 stateless 애플리케이션에서 이상적

  • 프로비저닝

    • 프로비저닝(provisioning)은 사용자의 요구에 맞게 시스템 자원을 할당, 배치, 배포해 두었다가 필요 시 시스템을 즉시 사용할 수 있는 상태로 미리 준비해 두는 것을 말한다
  • Infrastructure as a Service(IaaS)

    • 클라우드 서비스의 종류
    • 개발사에 제공되는 물리적 자원을 가상화
    • 컴퓨팅 리소스를 가상화하여 제공하는 것
  • Platform as a Service(PaaS)

    • 개발사에 제공되는 플랫폼을 가상화
  • Software as a Service(SaaS)

    • 고객에게 제공되는 소프트웨어를 가상화
    • 인터넷을 통하여 응용프로그램 제공?

장점

  • 서버리스 컴퓨팅은 개발자 생산성을 높이고 운영 비용을 줄일 수 있다.
  • 인프라를 명시적으로 설명할 필요를 줄여줌으로써 DevOps 도입을 지원
  • BaaS의 모든 구성 요소를 통합해 애플리케이션 개발을 간소화
  • 항상 자체 서버를 실행하고 관리하는 대신 필요한 만큼 클라우드 기반 컴퓨팅 시간에 대해 비용을 지불

단점

  • 자체 서버를 실행하지 않거나 자체 서버측 로직을 제어하지 않는 데 따른 단점
  • 클라우드 제공업체는 자사 구성 요소가 상호작용하는 방법을 엄격히 제한할 수 있어, 사용자 시스템의 유연성과 커스터마이징 수준에 영향을 준다
  • 특정 벤더에 종속성을 가진다

Serverless Framework

  • 개발, 배포, 트러블슈팅, 보안관리를 적은 비용으로 할 수 있도록 도와주는 프레임워크
  • CLI와 hosted dashboard 로 구성되어 있으며, 이것을 통해 완전한 서버리스 애플리케이션 라이프사이클 관리를 제공해 준다
  • 정리하자면, 환경을 배포하고 운영하기 위한 도구
  • AWS 람다 사용하여 함수를 작성하고, AWS API Gateway 띄우고 SNS, Dynamo DB 설정하는 등 여러 설정 등을 대신해 준다

Get Started

  • Node와 NPM이 설치되어 있어야 합니다

    • 해당 명령어를 통해 설치를 확인할 수 있습니다
    # 각 버젼 확인
    npm -v
    node -v
# serverless 프레임워크 설치, sudo로 실행해야 합니다
npm install -g serverless
# node.js 용 serverless template을 다운로드합니다
# 기존 프로젝트에 serverless.yml 생성해서 해도 가능합니다
# spring boot의 경우에도 루트 경로에 serverless.yml 생성하면 됩니다
serverless --template-url=https://github.com/serverless/examples/tree/v3/aws-node-http-api

# Move into the newly created directory
cd your-service-name
# 서비스 이름
service: serverlessNodeJS

# 사용할 서버리스 프레임워크 버젼
frameworkVersion: '3'

# The cloud provider that we are going to use and the runtime environment.
provider:
  name: aws
  # 배포할 스테이지 (default: dev)
  stage: dev
  # 배포할 리전, 참고로 서울은 serverless dashboard가 지원 안함 (default: us-east-1)
  region: us-east-1
  # The AWS profile to use to deploy (default: "default" profile)
  profile: production
  # Use a custom name for the CloudFormation stack
  stackName: custom-stack-name
  # Optional CloudFormation tags to apply to APIs and functions
  tags:
    foo: bar
    baz: qux
  # Optional CloudFormation tags to apply to the stack
  stackTags:
    key: value
  # Method used for CloudFormation deployments: 'changesets' or 'direct' (default: changesets)
  # See <https://www.serverless.com/framework/docs/providers/aws/guide/deploying#deployment-method>
  deploymentMethod: direct
  # List of existing Amazon SNS topics in the same region where notifications about stack events are sent.
  notificationArns:
    - 'arn:aws:sns:us-east-1:XXXXXX:mytopic'
  stackParameters:
    - ParameterKey: 'Keyname'
      ParameterValue: 'Value'
  # Disable automatic rollback by CloudFormation on failure. To be used for non-production environments.
  disableRollback: true
  rollbackConfiguration:
    MonitoringTimeInMinutes: 20
    RollbackTriggers:
      - Arn: arn:aws:cloudwatch:us-east-1:000000000000:alarm:health
        Type: AWS::CloudWatch::Alarm
      - Arn: arn:aws:cloudwatch:us-east-1:000000000000:alarm:latency
        Type: AWS::CloudWatch::Alarm
  tracing:
    # Can only be true if API Gateway is inside a stack.
    apiGateway: true
    # Optional, can be true (true equals 'Active'), 'Active' or 'PassThrough'
    lambda: true

functions:
    # AWS 람다함수 이름
  hello:
        # 실행할 함수의 위치와 함수 이름
    handler: handler.hello
        # 발생할 이벤트
        events:
            # API 타입
      - httpApi:
                    # URL 경로
          path:
          method: get

Amazon API Gateway

Amazon API Gateway

AWS Lambda

node.js로 serverless 개발 시작하기

spring-boot로 serverless 개발 시작하기

# 필요한 dependency
implementation group: 'com.amazonaws.serverless', name: 'aws-serverless-java-container-springboot2', version: '1.6'
implementation group: 'com.amazonaws', name: 'aws-lambda-java-events', version: '3.10.0' // For deserialize AWS events

# 빌드 설정
task buildZipFull(type: Zip) {
    baseName = "springboot-serverless-test"
    from compileJava
    from processResources
    into('lib') {
        from(configurations.compileClasspath) {
            exclude 'tomcat-embed-*'
        }
    }
}

build.dependsOn buildZipFull

tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}
  • handelr를 생성해야 합니다
  • AWS Lambda의 요청을 spring message 로 convert 해주고, API Gateway의 이벤트를 Spring boot의 controller로 넘겨주는 역할을 수행합니다
public class StreamLambdaHandler implements RequestStreamHandler {
    private static SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;

    static {
        try {
            handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(SpringbootServerlessTestApplication.class);
            // If you are using HTTP APIs with the version 2.0 of the proxy model, use the getHttpApiV2ProxyHandler
            // method: handler = SpringBootLambdaContainerHandler.getHttpApiV2ProxyHandler(Application.class);
        } catch (ContainerInitializationException e) {
            // if we fail here. We re-throw the exception to force another cold start
            e.printStackTrace();
            throw new RuntimeException("Could not initialize Spring Boot application", e);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context)
            throws IOException {

        handler.proxyStream(inputStream, outputStream, context);
    }
}
  • serverless.yml
provider:
  name: aws
  runtime: java11
  timeout: 15

# 배포할 빌드 파일 경로
package:
  artifact: build/distributions/springboot-serverless-test-0.0.1-SNAPSHOT.zip

# 함수 설정
functions:
  getPoint:
  # 핸들러 경로  
    handler: com.example.serverless.StreamLambdaHandler::handleRequest
    events:
      - http:
          path: point
          method: get
          cors: true