AWS는 최근 여러 서비스와 런타임을 더 이상 사용하지 않습니다. 우리가 사랑하는 CodeCommit 및 기타 중요한 서비스의 중단을 통해 확인했듯이 Go1.x는 더 이상 AWS Lambda 기능에 대해 지원되지 않습니다.
오래된 튜토리얼 대부분을 배포하려고 하면 다음과 같은 오류가 발생할 수 있습니다.
Resource creation Initiated CREATE_FAILED AWS::Lambda::Function DemoFunction Resource handler returned message: "The runtime parameter of go1.x is no longer supported for creating or updating AWS Lambda functions. We recommend you use a supported runtime while creating or updating functions. (Service: Lambda, Status Code: 400, Request ID: 81f1f708-0a7a-40d0-8442-b9c16510d01f)" ROLLBACK_IN_PROGRESS AWS::CloudFormation::Stack lambda-go-gorilla The following resource(s) failed to create: [DemoFunction]. Rollback requested by user.
핵심 내용은 소프트웨어에서 변하지 않는 유일한 것은 변화라는 것입니다. 그러나 우리가 항상 명심해야 할 몇 가지 시대를 초월한 원칙이 있습니다:
이 문제를 해결하기 위해 저는 Go 애플리케이션을 배포하는 데 필요한 모든 인프라를 갖춘 최신 저장소를 만들기로 결정했습니다. 다음 두 가지 옵션을 사용할 수 있습니다.
GitHub에서 저장소를 여기에서 찾을 수 있습니다.
불변 인프라를 통해 우리가 원하는 것을 더 높은 수준에서 선언할 수 있으며 개발 및 프로덕션 환경이 최대한 가깝게 유지되도록 보장합니다. 예를 들어:
CompoundingFunction: Type: AWS::Serverless::Function Metadata: BuildMethod: makefile Properties: FunctionName: CompoundingFunction Architectures: ["arm64"] Handler: bootstrap Runtime: provided.al2 CodeUri: ./functions/CompoundingFunction/ MemorySize: 512 Timeout: 10 Environment: Variables: COMPOUNDING_TABLE_NAME: !Ref CompoundingTable Policies: - DynamoDBCrudPolicy: TableName: !Ref CompoundingTable Events: ApiGatewayPost: Type: Api Properties: RestApiId: !Ref ApiGateway Path: /compounding Method: POST
좋은 테스트 세트가 있다면 리팩터링을 두려워하지 마세요. 리팩토링은 소프트웨어 개발에 있어 필수적인 활동입니다. 이름은 모듈, 함수, 패키지, 변수 등 모든 곳에 나타나므로 중요합니다.
package main import ( "context" "encoding/json" "fmt" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" ) // Response is the structure for the response JSON type Response struct { Message string `json:"message"` GainsPerYear []float64 `json:"gainsPerYear"` } type Request struct { Principal float64 `json:"principal"` AnnualRate float64 `json:"annualRate"` Years int `json:"years"` } func HelloHandler(ctx context.Context, event events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { var req Request err := json.Unmarshal([]byte(event.Body), &req) if err != nil { return createResponse(400, "Invalid request body") } fmt.Println("Request", req) gainsPerYear := CalculateCompoundInterest(req.Principal, req.AnnualRate, req.Years) fmt.Println(gainsPerYear) response := Response{ Message: "Calculation successful", GainsPerYear: gainsPerYear, } body, err := json.Marshal(response) if err != nil { return createResponse(500, "Error marshalling response") } return createResponse(200, string(body)) } func createResponse(statusCode int, body string) (events.APIGatewayProxyResponse, error) { return events.APIGatewayProxyResponse{ StatusCode: statusCode, Body: body, Headers: map[string]string{"Content-Type": "application/json"}, }, nil } func main() { lambda.Start(HelloHandler) }
서버리스 애플리케이션에서는 단위 테스트가 중요하지만 통합 테스트도 포함하는 것을 잊지 마세요. 이러한 애플리케이션의 대부분은 비즈니스 문제를 해결하기 위해 통합 및 정책에 의존하기 때문입니다.
func TestCalculateCompoundInterest(t *testing.T) { principal := 100000000.0 annualRate := 10.0 years := 10 result := CalculateCompoundInterest(principal, annualRate, years) lastElement := round(result[len(result)-1], 2) expected := round(259374246.01, 2) if !reflect.DeepEqual(lastElement, expected) { t.Errorf("Expected %v, but got %v", expected, lastElement) } }
서버리스 아키텍처는 기본적으로 가용성이 높으며 이벤트 기반이므로 대부분의 운영 작업이 제거됩니다. 그러나 ECS와 컨테이너를 사용하기로 선택한 경우 로드 밸런서를 포함하여 서버 간에 트래픽을 분산시켜 가용성과 확장성을 모두 보장하는 것이 중요합니다.
CompoundingLoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Name: compounding-nlb Scheme: internet-facing Type: network Subnets: - !Ref PublicSubnetOne - !Ref PublicSubnetTwo
배포 파이프라인은 소프트웨어 제공 프로세스를 자동화합니다. 우리는 이 프로세스를 단순화하기 위해 Makefile을 만들었습니다. 이를 통해 단일 명령으로 반복적인 작업을 쉽게 배포하고 실행할 수 있습니다. 이 접근 방식은 배포 워크플로의 효율성과 일관성을 향상시킵니다.
추적, 로깅, 지표가 마련되어 있는지 확인하세요. 서버리스 애플리케이션을 사용하면 Tracing: Active를 추가하는 것만큼 간단하게 이러한 기능을 활성화할 수 있습니다. CloudWatch와 같은 중앙 위치에서 모든 로그를 확인하고 서비스 상호 작용을 모니터링하는 기능은 매우 중요합니다.
보안은 모든 애플리케이션에서 가장 중요합니다. Amazon Cognito를 사용하면 강력한 사용자 인증이 제공되고, API 키는 추가 제어 및 인증 계층을 추가하여 인증된 클라이언트만 API에 액세스할 수 있도록 보장합니다.
Auth: DefaultAuthorizer: CompoundingAuthorizer Authorizers: CompoundingAuthorizer: UserPoolArn: XXXX LambdaTokenAuthorizer: FunctionArn: !GetAtt LambdaTokenAuthorizerFunction.Arn FunctionPayloadType: REQUEST Identity: Headers: - Authorization ReauthorizeEvery: 100 AddDefaultAuthorizerToCorsPreflight: false
각 서비스, 사용자 및 구성 요소에 최소한의 필수 권한을 할당하여 공격 표면을 줄이고 무단 액세스를 방지합니다. 최소 권한 원칙:
Policies: - DynamoDBCrudPolicy: TableName: !Ref CompoundingTable
소프트웨어는 지속적으로 발전하고 있으며 일부 도구와 방식은 변경되지만 기본 원칙은 동일하게 유지됩니다. 불변의 인프라, CI/CD, 올바른 명명 규칙, 강력한 테스트 전략, API의 보안, 애플리케이션의 효율성이 필요합니다. 그래서 이 프로젝트를 서버리스 방식으로 다시 만들기로 결정했습니다.
엔지니어가 되어 소프트웨어를 통해 사회에 가치를 창출하기에 이보다 더 좋은 때는 없었습니다.
기사가 마음에 드셨다면 제 블로그 jorgetovar.dev를 방문해 주세요.
부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.
Copyright© 2022 湘ICP备2022001581号-3