일반적으로 서버리스라고 불리는 서비스형 기능(FaaS)에 대한 많은 논의가 있었습니다. 이러한 기능을 제공하는 인기 있는 공급업체로는 Amazon이 있습니다. AWS 람다 서비스. 지원되는 람다 기술(예: Node.js)로 함수를 생성하고, AWS Lambda에 배포하고, AWS API 게이트웨이를 통해 액세스하고, 수요에 맞게 자체적으로 확장할 수 있습니다.
AWS Lambda와 함께 Node.js를 사용하여 다음과 같은 플레이버에서 NoSQL 문서와 통신할 수 있는 함수를 만드는 방법을 살펴보겠습니다. 카우치베이스 서버.
앞으로는 클라우드 어딘가에서 실행 중인 클러스터 또는 단일 인스턴스의 Couchbase Server가 있다고 가정합니다. 즉, 로컬 컴퓨터에서 Couchbase를 실행하는 경우 이 프로젝트는 작동하지 않습니다. 이 프로젝트는 AWS에서 실행하고 있기 때문에 Couchbase가 EC2 인스턴스로 존재하는 것이 합리적일 수 있습니다. 이 작업은 다음과 같이 수행할 수 있습니다. 사용 가능한 AMI 사용.
서버리스 프레임워크로 Lambda 및 API 게이트웨이용 FaaS 프로젝트 만들기
이전에 AWS Lambda 및 AWS API Gateway로 작업해 본 적이 있다면, 처음부터 무언가를 시작한 다음 배포하는 것이 그다지 즐거운 경험이 아니라는 것을 알고 계실 것입니다. 이 과정을 조금 더 쉽게 하기 위해, 저희는 서버리스 프레임워크를 사용하면 람다 기능을 개발하는 방식을 변경하지 않고도 많은 작업을 처리할 수 있습니다.
이미 Node.js가 설치되어 있다고 가정하고 다음을 실행하여 서버리스 프레임워크 CLI를 가져옵니다:
1 |
npm 설치 -g 서버리스 |
CLI를 사용하면 AWS에 국한되지 않고 사용 가능한 템플릿을 기반으로 새 프로젝트를 생성할 수 있습니다. CLI로 새 프로젝트를 생성하려면 다음을 실행합니다:
1 |
서버리스 create --템플릿 aws-nodejs --경로 ./my-프로젝트 |
저희는 앞으로 내 프로젝트 디렉토리를 생성합니다. 여기서부터 상황이 조금 이상해질 수 있습니다.
Node.js 프로젝트에는 UUID 값 생성을 위한 패키지인 Couchbase SDK와 데이터 유효성 검사를 위한 패키지가 필요합니다. 문제는 제가 Mac을 사용하고 있고 Lambda가 특별한 버전의 Linux를 사용한다는 것입니다. Mac에서 종속 요소를 다운로드하려고 하면 Linux와 호환되지 않습니다. 대신 몇 가지 단계를 거쳐야 합니다.
라는 제목의 온라인 기사가 있습니다, AWS 람다에서 네이티브 종속성 사용에서 Docker를 사용하여 Lambda에서 작동하는 네이티브 프로젝트 종속성 작업을 수행하는 방법을 설명합니다.
요약하면, 현재 프로젝트 디렉토리에 Docker가 설치되어 있고 CLI가 있는 상태에서 다음을 실행할 수 있습니다:
1 2 |
도커 pull 아마존 리눅스 도커 실행 -v $(pwd):/람다-프로젝트 -it 아마존 리눅스 |
위의 명령은 Amazon Linux 이미지를 가져와 컨테이너를 배포하여 현재 프로젝트 디렉터리를 컨테이너 볼륨으로 매핑합니다. 컨테이너 내에서 Node.js를 설치하고 패키지 종속성을 얻을 수 있습니다. 이 작업을 수행하는 방법을 알아보려면 이전에 작성한 글을 확인하세요, AWS Lambda에 네이티브 Node.js 종속성 배포하기.
프로젝트에 다음 세 가지 종속성을 설치해야 합니다:
1 2 3 |
npm 설치 카우치베이스 --저장 npm 설치 joi --저장 npm 설치 uuid --저장 |
Amazon Linux 요구 사항 때문에 계속 진행하지 못할 필요는 없습니다. 기본적으로 컨테이너 내에서 세 가지 명령을 실행하기만 하면 되고 컨테이너에는 매핑된 볼륨이 있으므로 얻은 모든 파일은 프로젝트에 직접 저장됩니다.
NoSQL 데이터베이스에 대한 CRUD 작업용 함수 개발하기
서버리스 프레임워크 프로젝트가 준비되었으니 이제 정말 중요한 것에 집중할 수 있습니다. 여기서 목표는 Couchbase NoSQL 문서 생성, 검색, 업데이트 및 삭제에 각각 하나씩 네 가지 함수를 만드는 것입니다. 바로 CRUD 함수 집합을 만드는 것입니다.
프로젝트의 handler.js 파일을 부트스트랩해야 하기 때문입니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
'엄격하게 사용'; const 카우치베이스 = require("couchbase"); const UUID = require("uuid"); const Joi = require("joi"); var 클러스터 = new 카우치베이스.클러스터("couchbase://your-server-here"); 클러스터.인증("demo", "123456"); var 버킷 = 클러스터.오픈버킷("예제"); 버킷.on("오류", 오류 => { 콘솔.dir(오류); }); 모듈.수출.create = (이벤트, 컨텍스트, 콜백) => { }; 모듈.수출.검색 = (이벤트, 컨텍스트, 콜백) => { }; 모듈.수출.업데이트 = (이벤트, 컨텍스트, 콜백) => { }; 모듈.수출.삭제 = (이벤트, 컨텍스트, 콜백) => { }; |
위의 코드에서는 프로젝트 종속 요소를 가져오고, Couchbase 클러스터에 연결하고, 해당 클러스터로 인증하고, 특정 버킷을 열었습니다. 실제 정보를 반영하도록 Couchbase 정보를 변경해야 합니다.
앞서 언급한 네 가지 기능도 만들었습니다. 그러나 현재로서는 이러한 함수는 아무 기능도 수행하지 않습니다.
여기서 주목해야 할 중요한 사항이 있습니다. 데이터베이스 연결 로직은 함수 외부에서 이루어지고 있습니다. 함수를 호출할 때마다 데이터베이스에 연결하는 것은 비용이 많이 드는 작업입니다. 이 정보를 외부로 옮기면 모든 람다 함수 컨테이너에서 여전히 액세스할 수 있습니다.
부터 시작하여 create
함수입니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
모듈.수출.create = (이벤트, 컨텍스트, 콜백) => { 컨텍스트.callbackWaitsForEmptyEventLoop = false; var 스키마 = Joi.객체().키({ 이름: Joi.문자열().필수(), 성: Joi.문자열().필수(), 유형: Joi.문자열().금지됨().기본값("사람") }); var 데이터 = JSON.parse(이벤트.body); var 응답 = {}; var 유효성 검사 = Joi.유효성 검사(데이터, 스키마); 만약(유효성 검사.오류) { 응답 = { statusCode: 500, body: JSON.문자열화(유효성 검사.오류.세부 정보) }; 반환 콜백(null, 응답); } var id = UUID.v4(); 버킷.삽입(id, 유효성 검사.값, (오류, 결과) => { 만약(오류) { 응답 = { statusCode: 500, body: JSON.문자열화({ 코드: 오류.코드, 메시지: 오류.메시지 }) }; 반환 콜백(null, 응답); } 데이터.id = id; 응답 = { statusCode: 200, body: JSON.문자열화(데이터) }; 콜백(null, 응답); }); }; |
위의 코드에는 많은 일이 일어나고 있으므로 이를 세분화해야 합니다.
먼저 다음 줄을 추가합니다:
1 |
컨텍스트.callbackWaitsForEmptyEventLoop = false; |
위의 줄을 추가함으로써 함수가 응답을 기다리는 방식을 변경하고 있습니다. false로 설정하지 않으면 뒤따르는 비동기 작업은 완료되기 전에 시간 초과될 가능성이 높습니다.
1 2 3 4 5 6 7 8 |
var 스키마 = Joi.객체().키({ 이름: Joi.문자열().필수(), 성: Joi.문자열().필수(), 유형: Joi.문자열().금지됨().기본값("사람") }); var 데이터 = JSON.parse(이벤트.body); var 응답 = {}; var 유효성 검사 = Joi.유효성 검사(데이터, 스키마); |
사용자 입력을 기반으로 데이터를 생성할 것이므로 해당 사용자 입력의 유효성을 검사하는 것이 좋습니다. 다음을 사용하여 Joi를 사용하여 유효성 검사 스키마를 생성하고 이를 사용하여 이벤트와 함께 전달된 데이터 본문의 유효성을 검사할 수 있습니다. Joi는 이전 글에서 사용했던 유효성 검사 프레임워크라는 것을 알고 계실 것입니다, Node.js, Hapi 및 Couchbase NoSQL로 RESTful API 만들기.
1 2 3 4 5 6 7 |
만약(유효성 검사.오류) { 응답 = { statusCode: 500, body: JSON.문자열화(유효성 검사.오류.세부 정보) }; 반환 콜백(null, 응답); } |
유효성 검사 오류가 있는 경우 500 오류를 응답으로 다시 보냅니다. 그렇지 않으면 새 문서 키를 생성하여 Couchbase Server에 저장합니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
var id = UUID.v4(); 버킷.삽입(id, 유효성 검사.값, (오류, 결과) => { 만약(오류) { 응답 = { statusCode: 500, body: JSON.문자열화({ 코드: 오류.코드, 메시지: 오류.메시지 }) }; 반환 콜백(null, 응답); } 데이터.id = id; 응답 = { statusCode: 200, body: JSON.문자열화(데이터) }; 콜백(null, 응답); }); |
람다가 예상하는 응답 형식에 유의하세요. 응답에는 statusCode
및 body
.
이제 검색
함수입니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
모듈.수출.검색 = (이벤트, 컨텍스트, 콜백) => { 컨텍스트.callbackWaitsForEmptyEventLoop = false; var 응답 = {}; var 문 = "SELECT META().id, `" + 버킷._name + "`.* FROM `" + 버킷._name + "` WHERE type = 'person'"; var 쿼리 = 카우치베이스.N1qlQuery.fromString(문); 버킷.쿼리(쿼리, (오류, 결과) => { 만약(오류) { 응답 = { statusCode: 500, body: JSON.문자열화({ 코드: 오류.코드, 메시지: 오류.메시지 }) }; 반환 콜백(null, 응답); } 응답 = { statusCode: 200, body: JSON.문자열화(결과) }; 콜백(null, 응답); }); }; |
의 목표는 검색
함수는 N1QL을 사용하여 Couchbase의 모든 문서를 쿼리하고 반환하는 것입니다. 결과에 따라 람다 응답의 형식을 적절히 지정합니다. 참고로 우리는 callbackWaitsForEmptyEventLoop
값으로 설정합니다. 이는 각 함수에서 발생합니다.
구조화 방법 업데이트
함수를 구성한 방식과 유사합니다. create
함수입니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
모듈.수출.업데이트 = (이벤트, 컨텍스트, 콜백) => { 컨텍스트.callbackWaitsForEmptyEventLoop = false; var 스키마 = Joi.객체().키({ 이름: Joi.문자열().선택 사항(), 성: Joi.문자열().선택 사항() }); var 데이터 = JSON.parse(이벤트.body); var 응답 = {}; var 유효성 검사 = Joi.유효성 검사(데이터, 스키마); 만약(유효성 검사.오류) { 응답 = { statusCode: 500, body: JSON.문자열화(유효성 검사.오류.세부 정보) }; 반환 콜백(null, 응답); } var 빌더 = 버킷.mutateIn(이벤트.경로 매개변수.id); 만약(데이터.이름) { 빌더.대체("이름", 데이터.이름); } 만약(데이터.성) { 빌더.대체("성", 데이터.성); } 빌더.실행((오류, 결과) => { 만약(오류) { 응답 = { statusCode: 500, body: JSON.문자열화({ 코드: 오류.코드, 메시지: 오류.메시지 }) }; 반환 콜백(null, 응답); } 응답 = { statusCode: 200, body: JSON.문자열화(데이터) }; 콜백(null, 응답); }); }; |
스키마를 기반으로 몇 가지 데이터 유효성 검사를 수행하는 것으로 작업을 시작한다는 점에 주목하세요. 데이터가 유효한 것으로 간주되면 Couchbase에 대한 하위 문서 작업을 진행할 수 있습니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
var 빌더 = 버킷.mutateIn(이벤트.경로 매개변수.id); 만약(데이터.이름) { 빌더.대체("이름", 데이터.이름); } 만약(데이터.성) { 빌더.대체("성", 데이터.성); } 빌더.실행((오류, 결과) => { 만약(오류) { 응답 = { statusCode: 500, body: JSON.문자열화({ 코드: 오류.코드, 메시지: 오류.메시지 }) }; 반환 콜백(null, 응답); } 응답 = { statusCode: 200, body: JSON.문자열화(데이터) }; 콜백(null, 응답); }); |
기본적으로 요청에서 찾은 정보를 기반으로 돌연변이 빌더를 생성합니다. 추가된 돌연변이는 실행될 때 키에 대해 실행됩니다. 실행 결과는 Lambda의 응답으로 반환됩니다.
다음 사항에 유의하세요:
1 |
이벤트.경로 매개변수.id |
이것은 본문에서 제공되지 않는 데이터입니다. 다음 단계 중 하나에서 구성됩니다.
이제 남은 것은 삭제
함수입니다:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
모듈.수출.삭제 = (이벤트, 컨텍스트, 콜백) => { 컨텍스트.callbackWaitsForEmptyEventLoop = false; var 스키마 = Joi.객체().키({ id: Joi.문자열().필수() }); var 데이터 = JSON.parse(이벤트.body); var 응답 = {}; var 유효성 검사 = Joi.유효성 검사(데이터, 스키마); 만약(유효성 검사.오류) { 응답 = { statusCode: 500, body: JSON.문자열화(유효성 검사.오류.세부 정보) }; 반환 콜백(null, 응답); } 버킷.제거(데이터.id, (오류, 결과) => { 만약(오류) { 응답 = { statusCode: 500, body: JSON.문자열화({ 코드: 오류.코드, 메시지: 오류.메시지 }) }; 반환 콜백(null, 응답); } 응답 = { statusCode: 200, body: JSON.문자열화(데이터) }; 콜백(null, 응답); }); }; |
지금까지 모든 내용을 잘 따라가셨다면 삭제
함수는 전혀 새롭지 않게 보일 것입니다. 데이터의 유효성을 검사하고 데이터베이스에 대해 실행하는 것입니다.
함수가 생성되었으므로 이제 서버리스 프레임워크 구성 정보에 집중할 수 있습니다. 프로젝트의 서버리스.yml 파일을 열고 다음을 포함하세요:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
서비스: 카우치베이스-람다 공급자: 이름: aws 런타임: nodejs6.10 함수: create: 핸들러: 핸들러.create 이벤트: - http: 경로: create 메서드: post 검색: 핸들러: 핸들러.검색 이벤트: - http: 경로: 검색 메서드: get 업데이트: 핸들러: 핸들러.업데이트 이벤트: - http: 경로: 업데이트/{id} 메서드: put 삭제: 핸들러: 핸들러.삭제 이벤트: - http: 경로: 삭제 메서드: 삭제 |
위의 YAML 문서에서 가장 중요한 부분은 함수입니다. 각 함수에 이름을 붙이고 적절한 핸들러 함수에 연결했습니다. 각 함수의 이벤트
는 브라우저에서 이러한 함수가 호출되는 방식입니다. 브라우저에서 이벤트
는 AWS API 게이트웨이에 대한 구성입니다.
에서 이벤트
섹션에서는 경로 정보, 각 엔드포인트에 액세스할 수 있는 방법(GET 요청이든 POST 요청이든 다른 것이든), 모든 종류의 경로 변수를 정의합니다.
제가 기억하라고 했던 대사 기억하시죠?
1 |
이벤트.경로 매개변수.id |
이것은 id
값의 update/{id}
경로.
이 시점에서 프로젝트는 Amazon Web Services에 배포할 준비가 되었습니다.
API 게이트웨이 지원을 통해 AWS Lambda에 함수 배포하기
Amazon 공개 키 및 개인 키를 사용하여 서버리스 프레임워크를 구성하는 방법에 대해서는 자세히 다루지 않겠지만, 구성이 완료되었다는 가정 하에 배포에 대해 설명하겠습니다.
서버리스 프레임워크 CLI에서 다음을 실행합니다:
1 |
서버리스 배포 |
위의 명령은 함수 코드와 함께 node_modules 를 생성하여 AWS 클라우드로 푸시할 수 있습니다. 서버리스 프레임워크는 AWS 람다 및 API 게이트웨이의 구성에 대해 걱정할 필요가 없습니다. 서버리스.yml 파일을 만듭니다.
결론
방금 커뮤니케이션하는 방법을 보셨습니다. 카우치베이스 서버 를 AWS Lambda 및 AWS API 게이트웨이에서 제어하는 함수 집합에서 사용할 수 있습니다. 이는 애플리케이션이 활성화된 시간이 아니라 사용된 시간에 대해 요금이 청구되는 애플리케이션을 만들고자 할 때 유용합니다. 카우치베이스를 포함하는 것은 네이티브 Node.js 종속성을 제외하면 다른 Node.js 애플리케이션에 포함하는 것과 크게 다르지 않았습니다.
클라우드에서 Couchbase를 사용하기로 결정했다면 Lambda에 올바른 포트가 열려 있는지 확인하세요. 저는 SDK에 필요한 모든 포트를 여는 것을 잊어버리는 실수를 저질렀고, 이로 인해 약간의 문제가 발생했습니다.
카우치베이스 서버 사용에 대한 자세한 내용은 다음을 참조하세요. 카우치베이스 개발자 포털.
안녕하세요 닉,
저는 (AWS의) 카우치베이스 서버에 연결하고 테스트 텍스트를 반환하는 함수 하나만 있는 예제를 통해 이를 실행하는 방법을 살펴보고 있습니다.
이 오류로 인해 오류가 발생합니다:
"오류 메시지": "/var/lang/lib/libstdc++.so.6: 버전 `CXXABI_1.3.9`를 찾을 수 없습니다(/var/task/node_modules/couchbase/build/Release/couchbase_impl.node에서 필요).",
내 구글 푸가 실패하고 있습니다. 무엇이 문제인지 아시나요?
도커 이미지에서 C++를 업그레이드해야 하나요?
하지만 AWS의 컴파일러 버전 문제인 것 같습니다.