Golang微服务项目结构

时间:2017-08-19 21:00:10

标签: go microservices directory-structure

我正处于在Go中创建微服务应用程序的初始阶段,但由于处理导入路径和目录的方式,我不太确定构建项目文件的最佳方法是什么。

通常,项目在Java中看起来像这样:

|-- gateway_microservice
   |-- src
   |-- docker
|-- config_microservice
   |-- src
   |-- docker
|-- recommendation_microservice
   |-- src
   |-- docker
|-- users_microservice
   |-- src
   |-- docker

现在,如果我在Go中以相同的方式执行,导入路径会变得有些麻烦:

import (
       "fmt" 
       "github.com/user/myproject/gateway_microservice/src/package1"
       "github.com/user/myproject/gateway_microservice/src/package2"
)

此外,我听说惯用的方法是将所有main.go个文件放在一个单独的cmd目录中,这会增加混乱。它看起来像这样:

|-- cmd
   |-- gateway_microservice
      |-- main.go
   |-- config_microservice
      |-- main.go
   |-- recommendation_microservice
      |-- main.go
   |-- users_microservice
      |-- main.go
|-- gateway_microservice
   |-- src
   |-- docker
|-- config_microservice
   |-- src
   |-- docker
|-- recommendation_microservice
   |-- src
   |-- docker
|-- users_microservice
   |-- src
   |-- docker

在Go中构建像这样的项目的“正确”或惯用方法是什么?

5 个答案:

答案 0 :(得分:6)

这里的另一个答案是提倡将每个微服务放入自己的存储库中。可能有正当理由以这种方式拆分,但也可能有同样有效的理由想要将所有内容保存在一个存储库中(这实际上取决于您的项目/环境)

如果您想要一个存储库中的所有代码,您可以 - 您只需要遵循Go的包规则。 (这是一个很好的阅读:https://golang.org/doc/code.html#Workspaces

如果您混合使用命令和库,那么您在问题中提出的目录结构就会很接近,但您可能不需要src目录。下面是一个示例,说明具有库和命令的repo中的目录结构可能如何显示:

lib1/
-- some.go
-- source.go
lib2/
-- more.go
-- source.go
cmd/
-- microservice1/
   -- main.go
-- microservice2/
   -- anothermain.go

要使用此存储库,您可以在系统的Go工作区内克隆它(请参阅上面我分享的链接)。假设您的存储库位于github.com/mybiz/project中,而您的GOPATH~/go,则工作区将如下所示:

~/go/src/github.com/mybiz/
  -- project/
     <clone repo in here>

文件cmd/microservice1/main.go将通过相对于lib1的预期路径包含库$GOPATH/src,如下所示:

import "github.com/mybiz/project/lib1"

现在,您的代码可以使用lib1下的文件中声明的包名称访问该包中的导出符号...通常只是:

package lib1

cmd/microservice1/main.go中,通过上面的导入,您可以使用lib1符号,如下所示:

lib1.CallMe()

我希望这有助于明确Go的目录结构如何运作。

答案 1 :(得分:4)

我正在构建它; mono-repo per。项目方法。考虑到这些服务密切相关:

github.com/user/some_project/
├── pkg/ (common own-created packages for all services)
|   ├── errors/
|   ├── log/
|   ├── metrics/
|   ├── sd/
|   |   ├── consul/
|   |   └── kubernetes/
|   └── tracing/
├── services/
|   ├── account/
|   |   ├── pb/
|   |   |   ├── account.proto
|   |   |   └── account.pb.go
|   |   ├── handler.go
|   |   ├── main.go
|   |   ├── main_test.go
|   |   ├── Dockerfile
|   |   └── README.md
|   ├── auth/
|   ├── frontend/
|   └── user/
├── vendor/ (common vendor-packages for all services)
├── docker-compose.yml
├── go.mod
├── go.sum
├── Makefile
└── README.md

备选方案2:

github.com/user/some_project/
├── pkg/
├── service.account/
|   ├─ cmd/
|   |  └─ main.go
|   ├─ pb/
|   ├─ Dockerfile
|   ├─ go.mod
|   └─ go.sum
├── service.auth/
├── service.frontend/
├── service.user/
├── docker-compose.yml
├── go.mod (used primarly for packages in the /pkg dir.)
├── go.sum
├── Makefile
└── README.md

随着go-modules的推出,我更倾向于第二种选择。

稍后,当您启动第二个宏/微/纳服务项目时,/ pkg文件夹中的许多这些包也将在那里被要求。该怎么办?复制粘贴?没有!相反,从项目中提取这些包,即日志,指标,并制作自己的工具包。

请记住,如果您使用某种CI / CD(您确实应该),您可以选择编写放置在项目根目录中的脚本,该脚本只会检测您在存储库中所做的更改,因此只会检测受影响的服务将建成并交付。有几个例子可以做到这一点。

答案 2 :(得分:3)

如何组织我的项目?

|-- github.com/avelino/service1
   |-- Dockerfile
   |-- main.go
|-- github.com/avelino/service2
   |-- Dockerfile
   |-- main.go
|-- github.com/avelino/service3
   |-- Dockerfile
   |-- main.go

软件包

所有Go代码都被组织成包。 Go中的包只是一个目录/文件夹,里面有一个或多个.go文件。 Go包提供隔离和组织代码,类似于目录/文件夹在计算机上组织文件的方式。

所有Go代码都存在于一个包中,一个包是访问Go代码的入口点。了解和建立包的良好实践对于编写有效的Go代码非常重要。

答案 3 :(得分:3)

感谢@ karl-andresen。我正在针对同一主题进行研究,并提出了以下结构,希望对您有所帮助

github.com/username/container/
├── pkg/ ('username' created packages - common for all services & reusable in other projects)
|   ├── errors/
|   ├── log/
|   ├── metrics/
|   ├── infra/     (sub category in packages)
|   |   ├── consul/
|   |   └── kubernetes/
|   └── tracing/
├── services/ (where all microservices will be imported as submodules - may or may not be reused)
|   ├── account/
|   |   ├── handler.go
|   |   ├── handler_test.go (unit testing, note filename with '_test')
|   |   ├── main.go
|   |   ├── main_test.go    (another unit testing)
|   |   ├── account.cfg     (configuration file for account microservice)
|   |   ├── submodule/      (sub directory)
|   |   |   ├── submodule.go
|   |   |   └── submodule_test.go   (submodule unit test)
|   |   ├── Dockerfile
|   |   └── README.md
|   ├── auth/
|   ├── booking/
|   └── user/
├── api/ (OpenAPI/Swagger specs, JSON schema files, protocol definition files.)
|   ├── proto/  (protocol buffer files)
|   |   ├── v1/
|   |   |   ├── account.proto
|   |   |   ├── account.pb.go
|   |   |   ├── booking.proto
|   |   |   └── booking.pb.go
|   |   └── v2/
|   └── rest/   (json files)
|       ├── v1/
|       |   ├── booking.json
|       |   └── account.json
|       └── v2/
├── configs/ (project config settings, default configs, file templates)
├── scripts/ (Scripts to perform various build, install, analysis, etc operations.)
├── build/ (Packaging and Continuous Integration.)
├── test / (system and module level tests)
├── docs/ (project documents folder)
├── examples/ (project examples for service interactions)
├── third_party/ (all open source, third party codes, where applicable fork and add as submodule)
├── githooks/ (project git hooks)
├── assets/ (common assests for all services)
├── Makefile
├── README.md
└── docker-compose.yml

答案 4 :(得分:0)

每个微服务都应该是一个独立的服务,并通过网络使用RESTful,RPC或消息传递相互通信。设计微服务以确保易于运输时,遵循12 Factor of App是一个优点。查看typical-go-server,获取有关如何进行微服务友好项目的示例。