[JAVA] I thought about how to make it serverless while avoiding vendor lock-in

This is the 19th day article of Serverless Architecture Advent Calendar 2016.

While a serverless architecture configuration is likely to have operational cost benefits, it is strongly dependent on a particular cloud vendor when simply ridden. If possible, I'd like to see if AWS's API Gateway or Lambda suddenly terminates its service. Therefore, based on the definition of Swagger, I created a tool called Swagger Code Builder so that it can be operated with multiple types of configurations.

It's similar to Swagger CodeGen, but the structure of the project is very different, so swagger-parser I tried to recreate it by diverting only api / swagger-parser).

Aimed composition

Normal configuration

\o/         +-----+   +-----------+
 | -------->|Nginx|-->|File System|
/ \         +-----+   +-----------+
User           |
               |
               |
               |  +---------------+   +----+   +-----+
               +->|Spark Framework|-->|Java|-->|MySQL|
                  +---------------+   +----+   +-----+

The Spark Framework (http://sparkjava.com/) is a Java micro-framework similar to Sinatra in Ruby and Flask in Python. Spring Boot was fine, but I chose the one that seems lighter (I'll explain later, but it may have been a failure). Please also refer to Past Articles regarding the use of Spark Framework.

Serverless configuration

\o/         +----------+   +--+
 | -------->|CloudFront|-->|S3|
/ \         +----------+   +--+
User              |
                  v
            +-----------+   +------+   +---------+
            |API Gateway|-->|Lambda|-->|Dynamo DB|
            +-----------+   +------+   +---------+

I think there are various ways to use Cognito for authentication, but I will focus on this configuration once. Even though it's Lambda, Java is because many people in today's company can use Java. If you use JavaScript more, node.js, Express seems to be better. Personally, I prefer Python and Flask, but there seems to be something called Zappa in this field. It differs from the rumored Serverless Framework in that it aims to be compatible.

strategy

Controller layer

Automatically generate code for each configuration from the Swagger definition so that you can write caller-independent code. The developer writes the code that receives and returns the POJO according to the convention, and the caller translates the automatically generated code according to each configuration.

#Logic template according to the rules
./swagger-code-builder \
    --structure java-services \
    --api-spec-path swagger-spec.yaml
#Template of normal composition
./swagger-code-builder \
    --structure sparkjava \
    --api-spec-path swagger-spec.yaml
#Serverless configuration template
./swagger-code-builder \
    --structure java-awsserverless \
    --api-spec-path swagger-spec.yaml \
    --aws-region ap-northeast-1 \
    --aws-account-id [Account ID]

However, I'm giving up on resolving library and object dependencies and writing them individually. I will write the dependencies of Gradle, the Module of Guice used in Spark Framework, and the constructor of Lambda by hand. I think that this area can be simplified if DI is used well, but it is not well organized yet.

Also, the code that converts the Spark Framework Request object is automatically generated, but if you want to use something other than the automatically generated object for the conversion destination, this conversion also needs to be reworked. Also, the automatic generation of POJOs like Swagger CodeGen is still half-baked. I think that it is necessary to cooperate with the persistence layer in this area as well, so I haven't done much.

Regarding API Gateway settings, Vendor Extension is automatically generated. So all you have to do is run the Lambda upload, import-rest-api, and grant permissions scripts. You can also set CORS and API Key as a whole as an option at the time of generation. All you have to do is click a few times on the AWS screen to complete the deployment.

Regarding the part that accepts requests before Controller (Nginx reverse proxy, Cloud Front Origin and Behavior), I should think about another method while looking at Kong. think.

Persistence layer

Divide the Model into logic (Service Layer) and specific data read / write part (Data Access Object Layer), and switch with Dependency Injection. As for DAO, I wrote twice the code by simple calculation, so it seems that another problem solving is needed around here.

Working with DynamoDB in JDBC seems to be a few things in proprietary, but it doesn't seem to come out in open source. RDB ← → DynamoDB handles List, Map, Set, and DynamoDB ← → Cassandra seems to be troublesome to handle type definitions. Although it is not included in the main body, Spring may have been better considering the existence of Spring Data DynamoDB.

Finally

Swagger Code Builder is a tool with many challenges, but it is actually used for developing small in-house tools. In particular, I think it's quite grateful that you don't have to mess around with the API Gateway integration on the screen. If you want to develop a serverless architecture that avoids vendor lock-in, please give it a try. We look forward to your feedback and issues.

Recommended Posts

I thought about how to make it serverless while avoiding vendor lock-in
I thought about how to use Swift's willSet did Set properly.
How to make shaded-jar
How to deal with the type that I thought about writing a Java program for 2 years
Java --How to make JTable
[Swift] I thought about compare
[Rails] How to make seed
About the matter that I was addicted to how to use hashmap
I tried to make it an arbitrary URL using routing nesting
[Introduction to JSP + Servlet] I played with it for a while ♬
What I thought about when I started migrating from Java to Kotlin