An API Gateway written in GO
that uses CloudWeGo Kitex
and Hertz
frameworks to develop an API Gateway that accepts HTTP
requests encoded in JSON
format, Utilising the Generic-Call feature of Kitex
to translate these requests into Thrift
binary format requests. The API Gateway will then proceed to forward the translated requests to one of the backend RPC
servers obtained from the registry centre.
- Client sends HTTP request with a JSON body with a "FirstNum" and "SecondNum" attribute.
- Hertz server processes the request and sends it to the Kitex Servers.
- A generic Kitex server will be generated and registered in the
etcd
registry. - Kitex server will process the request and convert it into
Thrift Binary Format
before sending it to the RPC servers. - The RPC servers will process the
addition
request and returns the response. - The API gateway will process and encode the response as an HTTP Response.
- For load testing and benchmarking analysis, please refer to Locust-ReadMe
- For unit testing, please refer to Script-testing-ReadMe
Before running the project, make sure you install the following,
Make sure etcd
is running.
- Instructions here for
Mac
users. If your machine is running onWindows
, unzip the folder and run theetcd
application in the folder.
In the gateway-server
directory, run go run .
in the terminal. (This runs the API-Gateway's HTTP server)
From inside the microservices directory, cd
into the Multiplication-service
directory. Then run the command go run .
(You can choose to follow the same steps to run the Name-service
which is also located in the microservices directory)
Test with Postman
using the following post request:
Address: http://127.0.0.1:8080/Multiplication/v1/multiplyNumbers
with the JSON body of:
{
"FirstNum" : "1",
"SecondNum" : "2"
}
Anticipate a response of:
{
"Product": "2"
}
Similarly you can test the Name
service using the following POST
request details:
Address: http://127.0.0.1:8080/Name/v1/helloName
with the JSON body of:
{
"Name": "Winne The Pooh"
}
Anticipate a response of:
{
"HelloResp": "Hello, Winne The Pooh"
}
That is all for testing the service on the gateway!
To create a new service from scratch, you must first create its IDL file. For our gateway, this is written in Apache Thrift.
For this demo, we will be creating a new service called the Addition
service. The IDL file for the Addition
service is as follows:
namespace go addition.management
struct AdditionRequest {
1: required string FirstNum;
2: required string SecondNum;
}
struct AdditionResponse {
1: string Sum;
}
service AdditionManagement {
AdditionResponse addNumbers(1: AdditionRequest req);
}
Once you have your IDL
file ready, head over to our IDL storage repo: [IDL Repo](https://github.com/ararchch/api-gateway-idl)
Create a new branch that branches from main
. Name this branch with your service's name. Make sure that this is the service name you use from this point on, particularly for service registry in the future. If there is a mismatch, the gateway will not work as intended as this name is used to map the service to its IDL
via GitHub
branches.
Upload your IDL
file into this branch. This gateway supports versioning so you can upload multiple versions of the IDL
over time. We recommend you follow the format of naming thrift files v1.thrift
, v2.thrift
and so on, however, you can change the version name if you wish, just ensure that you use it consistently throughout the rest of the gateway implementation. In our case, this has already been done for you with the v1.thrift
file in the Addition
branch.
Once you have uploaded your IDL
to your branch, it should be accessible via https://raw.githubusercontent.com/ararchch/api-gateway-idl/[service]/[version].thrift
Do check that it works, before proceeding. Eg: https://raw.githubusercontent.com/ararchch/api-gateway-idl/Addition/v1.thrift
Navigate into the microservices
directory, and run the generate_service.go
program using the following command:
go run generate_service.go [service] [version]
In our demo, this would be go run generate_service.go Addition v1
.
This should generate a directory within the microservices
directory, called [ServiceName]-service-[version]
. Eg: Addition-service-v1
NOTE You may notice that the pre-implemented services do not follow this convention. This is because they were generated before we realised that a potential clash may arise if there are multiple versions of IDLs used to generate the same service. As such we changed the directory naming convention to compensate for any future generated directories, however, the Multiplcation and Name services still follow the previous implementation.
Navigate into this generated directory (Addition-service-v1
), and open the handler.go
file. This is where you will enter the logic for the microservice. In the case of Addition, add the following code to the AddNumbers
method:
// parse int from string of First Number
firstNumInt, err := strconv.Atoi(req.FirstNum)
if err != nil {
panic(err)
}
// parse int from string of Second Number
secondNumInt, err := strconv.Atoi(req.SecondNum)
if err != nil {
panic(err)
}
// add two numbers together
finalSum := firstNumInt + secondNumInt
// convert finalSum to string and return response of type AdditionResponse and error = nil
return &management.AdditionResponse{
Sum: fmt.Sprintf("%d", finalSum),
}, nil
Remember to tidy your imports after this. In the same directory, proceed to the main.go
file and add the following code to generate and run servers that will run your microservice:
servers := utils.CreateMultipleServers(
3, // Number of servers you want to create to handle requests made to this microservice
"Addition", // name of microservice (servers will be registered under this name). **Make sure this is the same as the name of your branch in the idl repo**
new(AdditionManagementImpl), // the handler file that you defined in the previous step
management.NewServiceInfo(), // serviceInfo file containing generated details unique to your microservice
utils.RateLimit(1000, 1000), // optional rate limiter
)
utils.RunServers(servers)
Note that this uses a number of useful methods offered by the utils
package within the gateway. You do not have to use them if you don't want to though. In addition Kitex
offers a number of more options for the gateway which have not been wrapped by the current utils package. You can feel free to add any into the CreateMultipleServers
method if you wish (after the RateLimit option)
Once you have done this, you have finished implementing your service!
Navigate into the gateway-server
directory, and run the go run .
command.
Navigate into the Addition-service-v1
directory and run go run .
as well.
Finally, you can test by sending a POST
request as follows:
Address: http://127.0.0.1:8080/Addition/v1/addNumbers
with the JSON body of:
{
"FirstNum" : "1",
"SecondNum" : "2"
}
Anticipate a response of:
{
"Sum": "3"
}
You have now fully utilised the gateway!