Other language:
This is a Go Microservice project with gRPC. It tries to find an appropriate application layout for a Go Microservice application. It applied Clean Architecture design and using dependency injection to inject concrete types into each function.
The following are a series of articles to explain the different areas of the application design:
Go Microservice with Clean Architecture: Application Layout
Go Microservice with Clean Architecture: Application Design
Go Microservice with Clean Architecture: Design Principle
Go Microservice with Clean Architecture: Coding Style
Go Microservice with Clean Architecture: Transaction Support
Go Microservice with Clean Architecture: Application Logging
Go Micro-service with Clean Architecture: Application Container
Go Micro-service with Clean architecture: Dependency Injection
This project is best to be used as a basic framework when creating a gRPC Microservice project. It already has rich built-in functionalities and is working, so there is no reason to start from scratch. The goal of the project is to build a flexible framework with basic functions, which can be extended easily. The application design followed "SOLID" design principle and Go's concise coding style, so it can be used as a living example of the application design and coding style when you try to enforce them in your code.
- Switch persistence layer implementation by changing the configuration file. Currently, it implemented MySQL and CouchDB. (It can be extended to support other SQL or NoSQL databases)
- Switch logging provider by changing the configuration file. Currently, it implemented ZAP and Logrus. ( It can be extended to support other logging providers, as long as they support common interfaces similar to ZAP and Logrus)
- Support business layer transaction (It doesn't support nested transaction or transactions across Microservices)
- Using Dependency Injection to create concrete types and wire the whole application together.
- Application configurations are saved in a YAML file.
- Application has three layers: use case, model and persistence. Each layer accesses other layers through interfaces.
- Outside functions are also accessed through interfaces.
- Dependency between different layers is only on interfaces instead of concrete types.
- Interfaces are defined in top level package and separated from concrete types.
- Each concrete type is defined in a separate sub-package and file
- Isolate different layers by package
- Isolate each use case by package
- Isolate each implementation ( for example database implementation) by package
- whenever a new feature is added, instead of modifying existing code, try to add new code
- Eliminate package level variables except in "container" package
- Minimize use of constants.
- Log full stack trace for errors
- Errors are only handled on top level
- Separation of concerns.
- Naming Convention. Short names for local variables , long name for types or interfaces.
Don't need to finish all steps in this section up-front to get the code up running. The simplest way is to get the code from github and run it and come back to install the part when there is a real need. However, it will encounter an error when accesses the database. So, I'd recommend you install at least one database ( MySQL is better), then most of the code will work.
go get github.com/jfeng45/servicetmpl
There are two database implementations, MySQL and CouchDB, but most functions are implemented in MySQL. You'd better install at least one of them.
Install MySQL
run SQL script in script folder to create database and table
The code works fine without it. CouchDB is created to show the feature of switching database by changing configuration.
Installation on Windows
Installation on Linux
Installation on Mac
CouchDB Example
Access "Fauxton" through browser: http://localhost:5984/_utils/# (login with: admin/admin).
Create new database "service_config" in "Fauxton".
Add the following document to the database ( "_id" and "_rev" are generated by database, no need to change it):
{
"_id": "80a9134c7dfa53f67f6be214e1000fa7",
"_rev": "4-f45fb8bdd454a71e6ae88bdeea8a0b4c",
"uid": 10,
"username": "Tony",
"department": "IT",
"created": "2018-02-17T15:04:05-03:00"
}
Without it, calling another Microservice piece won't work, the rest of application works fine. Please follow instructions in reservegrpc to set up the service.
cd [MySQLroot]/bin
mysqld
It should already have been started
Please follow instructions in reservegrpc to start the server.
In "main()" function of "main.go", there are two functions "testMySql()" and "testCouchDB()". "testMySql()" reads configurations from "configs/appConifgDev.yaml" and accesses MySQL. "testCouchDB()" reads from "configs/appConifgProd.yaml" and access CouchDB. There are multiple functions in "testMySql()", you can focus on testing one each time by commenting out others.
cd [rootOfProject]/cmd
go run main.go
Start gRPC Server
cd [rootOfProject]/cmd/grpcserver
go run grpcServerMain.go
Start gRPC Client
cd [rootOfProject]/cmd/grpcclient
go run grpcClientMain.go
MIT License