여러 백엔드 리소스를 Amazon API Gateway와 통합

18660 단어 APIGateway람다ECSAWS

전제



시스템 개발을 하고 있으면 「A기능은 Lambda로 만들어야 하고, B기능은 컨테이너로 만들어야 합니다만, 각각 실은 URI는 동일하게 해 두는 것이 REST적으로 깨끗하게 되는 것이군요」라는 것이 있다. … 아니, 별로 없나? 어쨌든, 그럴 때는 nginx라든지에서 프록시를 만들어 나누어도 좋지만, 모처럼 퍼블릭 클라우드를 사용하고 있기 때문에 매니지드 서비스 사용해보고 싶지,라고 생각해 보았다.

Spring Boot 웹 앱이 움직이는 컨테이너와 Lambda 함수가 각각 있는 구성.

Lambda 함수



이 기사를 위해 재작성하는 것도 번거롭기 때문에, 이하의 기사로 만든 것을 전용한다.

Amazon API Gateway/ALB 백엔드에서 실행되는 Lambda 함수를 Java(Eclipse+maven)로 구현

Spring Boot 웹 앱의 움직이는 컨테이너



별로 고집도 없기 때문에, 적당한 파라미터를 받아 JSON을 돌려주는 컨테이너를 만들어 보자.
리소스는 /person .
매개 변수는 쿼리 또는 요청 본문(JSON)에서 id를 로드하고 해당 이름과 연령을 JSON으로 반환하는 사양입니다.

WebController.java
package com.example;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

@RestController
public class WebController {

    @RequestMapping("/person")
    @ResponseBody
    public Person response(
            @RequestBody(required = false) Person person,
            @RequestParam(name="id", required = false) String reqParamId) {
        Person response = null;
        String id = null;

        if( reqParamId != null ){
            id = reqParamId;
        }else{
            id = Integer.toString(person.getId());
        }

        if(id.equals("11111")) {
            response = new Person(Integer.parseInt(id), "Taro", 35);
        }else if(id.equals("22222")) {
            response = new Person(Integer.parseInt(id), "Hanako", 32);
        }

        return response;
    }
}

Person.java
package com.example;

public class Person {
    private int Id;
    private String Name;
    private int Age;

    // 適当な getter, setter
    // 中略

    public Person(int id, String name, int age) {
        Id = id;
        Name = name;
        Age = age;
    }
}

pom.xml은 spring-boot-starter, spring-boot-starter-web이 있으면 OK입니다.
빌드는 적당하게 mvn package하고 나서 적당한 Dockerfile로 docker build 해, ECR에 push한다.
이 근처도 이하의 과거 기사를 참고로.

AWS에서 SpringBoot 기반 웹 앱을 시작해 봅니다(Docker on EC2편/ECS+Fargate편)

API Gateway 설정



↓이런 느낌으로 정의한다.



자원
방법
전송처


LambdaTest
ANY
Lambda 함수

사람
GET
Spring Boot 웹 앱

사람
POST
Lambda 함수

사람
PUT
Spring Boot 웹 앱


손으로 포치포치 설정하는 것도 번거롭기 때문에, 아래의 Swagger+API Gateway 확장을 임포트한다.
이해하기 어려울지도 모르지만, 수입은 여기에서 가능.

---
swagger: "2.0"
info:
  description: "Created by AWS Lambda"
  version: "2020-04-25T10:56:39Z"
  title: "API GatewayのAPI名"
host: "[API Gatewayのドメイン]"
basePath: "/default"
schemes:
- "https"
paths:
  /LambdaTest:
    x-amazon-apigateway-any-method:
      responses:
        200:
          description: "200 response"
      x-amazon-apigateway-integration:
        uri: "[Lambda関数のARN]"
        responses:
          .*:
            statusCode: "200"
        passthroughBehavior: "when_no_match"
        httpMethod: "POST"
        type: "aws_proxy"
  /person:
    get:
      produces:
      - "application/json"
      responses:
        200:
          description: "200 response"
          schema:
            $ref: "#/definitions/Empty"
      x-amazon-apigateway-integration:
        uri: "http://[NLBのドメイン]/person"
        responses:
          default:
            statusCode: "200"
        passthroughBehavior: "when_no_match"
        connectionType: "VPC_LINK"
        connectionId: "[VPCLinkのID]"
        httpMethod: "GET"
        type: "http_proxy"
    post:
      produces:
      - "application/json"
      responses:
        200:
          description: "200 response"
          schema:
            $ref: "#/definitions/Empty"
      x-amazon-apigateway-integration:
        uri: "[Lambda関数のARN]"
        responses:
          default:
            statusCode: "200"
        passthroughBehavior: "when_no_match"
        httpMethod: "POST"
        contentHandling: "CONVERT_TO_TEXT"
        type: "aws_proxy"
    put:
      produces:
      - "application/json"
      responses:
        200:
          description: "200 response"
          schema:
            $ref: "#/definitions/Empty"
      x-amazon-apigateway-integration:
        uri: "http://[NLBのドメイン]/person"
        responses:
          default:
            statusCode: "200"
        passthroughBehavior: "when_no_match"
        connectionType: "VPC_LINK"
        connectionId: "[VPCLinkのID]"
        httpMethod: "GET"
        type: "http_proxy"
definitions:
  Empty:
    type: "object"
    title: "Empty Schema"

컨테이너에 대해서는, 내부용의 HTTP 서버를 통합하는 경우는, VPCLink로 연결한 NLB에 매달릴 필요가 있다. 이 근처 의 기사를 참고하자. 거의 이 기사와 하는 것은 같지만 신경쓰지 않는다…

그런데, 여기까지 하면, curl로 동작 확인을 해 보면, 기대대로의 동작이 되어 있는 것을 알 수 있다.

Lambda를 위한 요청 ①
$ curl --include -X GET https://[API Gatewayのドメイン]/default/LambdaTest
HTTP/2 200
date: Sat, 25 Apr 2020 12:52:11 GMT
content-type: application/json
content-length: 42
x-amzn-requestid: ********
x-amz-apigw-id: ********
x-amzn-trace-id: ********

{"greetings":"Hello from Lambda Ver 1.11"}

Lambda를 위한 요청②
$ curl --include -X POST https://[API Gatewayのドメイン]/default/person
HTTP/2 200
date: Sat, 25 Apr 2020 12:54:16 GMT
content-type: application/json
content-length: 42
x-amzn-requestid: ********
x-amz-apigw-id: ********
x-amzn-trace-id: ********

{"greetings":"Hello from Lambda Ver 1.11"}

Spring Boot 웹 앱용 요청 ①
$ curl --include -X GET https://[API Gatewayのドメイン]/default/person?id=11111
HTTP/2 200
date: Sat, 25 Apr 2020 12:55:24 GMT
content-type: application/json
content-length: 35
x-amzn-requestid: ********
x-amzn-remapped-connection: keep-alive
x-amz-apigw-id: ********
x-amzn-remapped-date: Sat, 25 Apr 2020 12:55:24 GMT

{"name":"Taro","id":11111,"age":35}[

Spring Boot 웹 앱용 요청②
$ curl --include -X PUT -H 'Content-Type:application/json' -d '{"id":"11111"}' https://[API Gatewayのドメイン]/default/person?id=11111
HTTP/2 200
date: Sat, 25 Apr 2020 12:56:33 GMT
content-type: application/json
content-length: 35
x-amzn-requestid: ********
x-amzn-remapped-connection: keep-alive
x-amz-apigw-id: ********
x-amzn-remapped-date: Sat, 25 Apr 2020 12:56:32 GMT

{"name":"Taro","id":11111,"age":35}

좋은 웹페이지 즐겨찾기