{"id":15154355,"url":"https://github.com/unusualcodeorg/gomicro","last_synced_at":"2025-09-17T21:34:45.477Z","repository":{"id":247198441,"uuid":"821704938","full_name":"unusualcodeorg/gomicro","owner":"unusualcodeorg","description":"gomicro is a Go microservices architecture using goserve micro framework. The blogging platform example is built using Kong API gateway, NATS, Mongo, Redis, and Docker. It implements authentication, authorization, and apikey protection.","archived":false,"fork":false,"pushed_at":"2024-07-07T08:52:52.000Z","size":245,"stargazers_count":22,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-05T04:51:15.526Z","etag":null,"topics":["backend","blogging","devops","docker","docker-compose","gin","gin-gonic","go","golang","goserve","jwt","kong","load-balancer","microservices","mongo","nats","redis","rest-api","server"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/unusualcodeorg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-29T07:45:13.000Z","updated_at":"2025-03-26T12:18:14.000Z","dependencies_parsed_at":"2024-07-09T12:50:17.761Z","dependency_job_id":null,"html_url":"https://github.com/unusualcodeorg/gomicro","commit_stats":null,"previous_names":["unusualcodeorg/gomicro"],"tags_count":2,"template":true,"template_full_name":null,"purl":"pkg:github/unusualcodeorg/gomicro","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unusualcodeorg%2Fgomicro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unusualcodeorg%2Fgomicro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unusualcodeorg%2Fgomicro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unusualcodeorg%2Fgomicro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unusualcodeorg","download_url":"https://codeload.github.com/unusualcodeorg/gomicro/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unusualcodeorg%2Fgomicro/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275668180,"owners_count":25506490,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-17T02:00:09.119Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backend","blogging","devops","docker","docker-compose","gin","gin-gonic","go","golang","goserve","jwt","kong","load-balancer","microservices","mongo","nats","redis","rest-api","server"],"created_at":"2024-09-26T17:21:58.997Z","updated_at":"2025-09-17T21:34:45.376Z","avatar_url":"https://github.com/unusualcodeorg.png","language":"Go","readme":"# gomicro - Go Microservices Architecture\n\n![Banner](.extra/docs/gomicro-banner.png)\n\n## Create Blogging Platform Microservices\nThis project creates a blogging API service using [goserve](https://github.com/unusualcodeorg/goserve) micro framework. In this project Kong is used as the API gateway and NATS for the interservice communication. Each service has its own Mongo database and Redis database (Note: a single mongo and redis server is used for multiple databases).\n\nThis project breaks down the monolithic go blog backend project provided at [goserve](https://github.com/unusualcodeorg/goserve) repository. It uses the [goserve](https://github.com/unusualcodeorg/goserve) REST API framework to build the auth_service, and blog_service.\n\n### Highlights\n- goserve micro architecture\n- kong API gateway\n- nats for microservices communication\n- custom kong go plugin for apikey validation\n- docker and docker-compose\n- mongo\n- redis\n\n\u003e More details on the REST part can be found at [goserve](https://github.com/unusualcodeorg/goserve) github repo\n\n### Project Directories\n1. **kong**: kong configuration and plugins\n2. **auth_service**: auth APIs code \n3. **blog_service**: blog APIs code \n\n**Helper/Optional Directories**\n1. **.extra**: mongo script for initialization inside docker, other web assets and documents\n2. **.tools**: RSA key generator, and .env copier\n3. **.vscode**: editor config and service debug launch settings\n\n## Microservice System Design\n\n**Request Flow**\n- client request comes to kong \n- `apikey-auth-plugin` calls `http://auth:8000/verify/apikey` within docker network\n- successful request is forwarded to the respective service\n- service returns with the appropriate response to kong\n- kong sends the response back to the client\n\n**Authentication**\n- users collection exists in the auth_service database\n- auth_service has logic to validate the JWT access token\n- auth_service validates the token using a middleware\n- blog_service asks auth_service to validate the token via nats messaging\n\n**Authorization**\n- users and roles collection exists in the auth_service database\n- auth_service checks the roles based on the asked role code\n- auth_service validates the role using a middleware\n- blog_service asks auth_service to validate a user's role via nats messaging\n\n\u003e This Authentication and Authorization implementation gives freedom to individual services to decide on the public, protected, and restricted APIs on its own.\n\n## The project runs in 2 configurations\n\n**1. Without Load Balancing**\n![Banner](.extra/docs/system.png)\n\n**2. With Load Balancing**\n![Banner](.extra/docs/system-load-balanced.png)\n\n## Installation Instructions\nvscode is the recommended editor - dark theme \n\n**1. Get the repo**\n\n```bash\ngit clone https://github.com/unusualcodeorg/gomicro.git\n```\n\n**2. Generate RSA Keys**\n```\ngo run .tools/rsa/keygen.go\n```\n\n**3. Create .env files**\n```\ngo run .tools/copy/envs.go \n```\n\n**4. Run Docker Compose**\nInstall Docker and Docker Compose. [Find Instructions Here](https://docs.docker.com/install/).\n\n\u003e Without Load Balancing\n```bash\ndocker-compose up --build\n```\nOR\n\n\u003e With Load Balancing\n```bash\ndocker-compose -f docker-compose-load-balanced.yml up --build\n```\n\nYou will be able to access the api from http://localhost:8000\n\n\u003e If having any issue make sure 8000 port is not occupied\n\n### API DOC\n[![API Documentation](https://img.shields.io/badge/API%20Documentation-View%20Here-blue?style=for-the-badge)](https://documenter.getpostman.com/view/1552895/2sA3dxCWsa)\n\n## Read the Articles to understand this project\n1. [How to Create Microservices — A Practical Guide Using Go](https://medium.com/@janishar.ali/how-to-create-microservices-a-practical-guide-using-go-35445a821513)\n2. [How to Architect Good Go Backend REST API Services](https://medium.com/@janishar.ali/how-to-architecture-good-go-backend-rest-api-services-14cc4730c05b)\n\n## Documentation\nInformation about the framework\n\u003e API framework details can be found at [goserve](https://github.com/unusualcodeorg/goserve) github repo\n\n### NATS\nTo communicate among services through nats a message struct is required\n\n```go\npackage message\n\ntype SampleMessage struct {\n  Field1 string `json:\"field1,omitempty\"`\n  Field2 string `json:\"field2,omitempty\"`\n}\n\nfunc EmptySampleMessage() *SampleMessage {\n  return \u0026SampleMessage{}\n}\n\nfunc NewSampleMessage(f1, f2 string) *SampleMessage {\n  return \u0026SampleMessage{\n    Field1: f1,\n    Field2: f2,\n  }\n}\n```\n\n### Controller\n- It implements `micro.Controller` from `github.com/unusualcodeorg/goserve/arch/micro`\n- `MountNats` is used to mount the endpoints that other services can call through nats \n- `MountRoutes` is used to mount the endpoints for http clients\n\n```go\npackage sample\n\nimport (\n  \"fmt\"\n  \"github.com/gin-gonic/gin\"\n  \"github.com/unusualcodeorg/gomicro/microservice2/api/sample/message\"\n  \"github.com/unusualcodeorg/goserve/arch/micro\"\n  \"github.com/unusualcodeorg/goserve/arch/network\"\n)\n\ntype controller struct {\n  micro.BaseController\n  service Service\n}\n\nfunc NewController(\n  authMFunc network.AuthenticationProvider,\n  authorizeMFunc network.AuthorizationProvider,\n  service Service,\n) micro.Controller {\n  return \u0026controller{\n    BaseController: micro.NewBaseController(\"/sample\", authMFunc, authorizeMFunc),\n    service:        service,\n  }\n}\n\nfunc (c *controller) MountNats(group micro.NatsGroup) {\n  group.AddEndpoint(\"ping\", micro.NatsHandlerFunc(c.pingHandler))\n}\n\nfunc (c *controller) MountRoutes(group *gin.RouterGroup) {\n  group.GET(\"/ping\", c.getEchoHandler)\n  group.GET(\"/service/ping\", c.getServicePingHandler)\n}\n\nfunc (c *controller) pingHandler(req micro.NatsRequest) {\n  fmt.Println(string(req.Data()))\n  msg := message.NewSampleMessage(\"from\", \"microservice2\")\n  c.SendNats(req).Message(msg)\n}\n\nfunc (c *controller) getEchoHandler(ctx *gin.Context) {\n  c.Send(ctx).SuccessMsgResponse(\"pong!\")\n}\n\nfunc (c *controller) getServicePingHandler(ctx *gin.Context) {\n  msg := message.NewSampleMessage(\"from\", \"microservice2\")\n  received, err := c.service.GetSampleMessage(msg)\n  if err != nil {\n    c.Send(ctx).MixedError(err)\n    return\n  }\n  c.Send(ctx).SuccessDataResponse(\"success\", received)\n}\n\n```\n\n### Service\n- `micro.RequestBuilder[message.SampleMessage]` is used to call other services to get `SampleMessage` through nats\n\n```go\npackage sample\n\nimport (\n  \"github.com/unusualcodeorg/gomicro/microservice2/api/sample/dto\"\n  \"github.com/unusualcodeorg/gomicro/microservice2/api/sample/message\"\n  \"github.com/unusualcodeorg/gomicro/microservice2/api/sample/model\"\n  \"github.com/unusualcodeorg/goserve/arch/micro\"\n  \"github.com/unusualcodeorg/goserve/arch/mongo\"\n  \"github.com/unusualcodeorg/goserve/arch/network\"\n  \"github.com/unusualcodeorg/goserve/arch/redis\"\n  \"go.mongodb.org/mongo-driver/bson\"\n  \"go.mongodb.org/mongo-driver/bson/primitive\"\n)\n\ntype Service interface {\n  FindSample(id primitive.ObjectID) (*model.Sample, error)\n  GetSampleMessage(data *message.SampleMessage) (*message.SampleMessage, error)\n}\n\ntype service struct {\n  network.BaseService\n  sampleQueryBuilder   mongo.QueryBuilder[model.Sample]\n  infoSampleCache      redis.Cache[dto.InfoSample]\n  sampleRequestBuilder micro.RequestBuilder[message.SampleMessage]\n}\n\nfunc NewService(db mongo.Database, store redis.Store, natsClient micro.NatsClient) Service {\n  return \u0026service{\n    BaseService:          network.NewBaseService(),\n    sampleQueryBuilder:   mongo.NewQueryBuilder[model.Sample](db, model.CollectionName),\n    infoSampleCache:      redis.NewCache[dto.InfoSample](store),\n    sampleRequestBuilder: micro.NewRequestBuilder[message.SampleMessage](natsClient, \"microservice1.sample.ping\"),\n  }\n}\n\nfunc (s *service) GetSampleMessage(data *message.SampleMessage) (*message.SampleMessage, error) {\n  return s.sampleRequestBuilder.Request(data).Nats()\n}\n\nfunc (s *service) FindSample(id primitive.ObjectID) (*model.Sample, error) {\n  filter := bson.M{\"_id\": id}\n\n  msg, err := s.sampleQueryBuilder.SingleQuery().FindOne(filter, nil)\n  if err != nil {\n    return nil, err\n  }\n\n  return msg, nil\n}\n\n```\n\n### NatsClient\nNatsClient should be created to connect and talk to nats\n```go\n  natsConfig := micro.Config{\n    NatsUrl:            env.NatsUrl,\n    NatsServiceName:    env.NatsServiceName,\n    NatsServiceVersion: env.NatsServiceVersion,\n    Timeout:            time.Second * 10,\n  }\n\n  natsClient := micro.NewNatsClient(\u0026natsConfig)\n```\n\u003e More details on nats can be found at [nats-io/nats.go](https://github.com/nats-io/nats.go/blob/main/micro/README.md). goserve creates a simple wrapper over this library.\n\n### If you are coming from [goserve](https://github.com/unusualcodeorg/goserve) framework for monolithic go architecture\n- `micro.Module[module]` should used for instance creation in place of `network.Module[module]`\n- `micro.NewRouter` should be used in place of `network.NewRouter`\n- `micro.BaseController` should be used in place of `network.BaseController`\n- `micro.Controller` should be used in place of `network.Controller`\n\n## Find this project useful ? :heart:\n* Support it by clicking the :star: button on the upper right of this page. :v:\n\n## More on YouTube channel - Unusual Code\nSubscribe to the YouTube channel `UnusualCode` for understanding the concepts used in this project:\n\n[![YouTube](https://img.shields.io/badge/YouTube-Subscribe-red?style=for-the-badge\u0026logo=youtube\u0026logoColor=white)](https://www.youtube.com/@unusualcode)\n\n## Contribution\nPlease feel free to fork it and open a PR.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funusualcodeorg%2Fgomicro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funusualcodeorg%2Fgomicro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funusualcodeorg%2Fgomicro/lists"}