Golang微服务项目结构
Golang microservice project 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 中构建这样的项目的 'correct' 或惯用方法是什么?
如何组织我的项目?
|-- github.com/avelino/service1
|-- Dockerfile
|-- main.go
|-- github.com/avelino/service2
|-- Dockerfile
|-- main.go
|-- github.com/avelino/service3
|-- Dockerfile
|-- main.go
套餐
所有 Go 代码都组织成包。 Go 中的包只是一个 directory/folder,其中包含一个或多个 .go 文件。 Go 包提供代码的隔离和组织,类似于 directories/folders 在计算机上组织文件的方式。
所有 Go 代码都在包中,包是访问 Go 代码的入口点。理解和建立围绕包的良好实践对于编写有效的 Go 代码很重要。
这里的另一个答案提倡将每个微服务放入自己的存储库中。以这种方式拆分东西可能有正当理由,但想要将所有内容都保存在一个存储库中也可能有同样正当的理由(这实际上取决于您的项目/环境)
如果你想将所有代码放在一个存储库中,你可以 - 你只需要遵循 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 工作区中(请参阅我上面分享的 link)。假设您的存储库位于 github.com/mybiz/project,而您的 GOPATH
是 ~/go
,工作区将如下所示:
~/go/src/github.com/mybiz/
-- project/
<clone repo in here>
文件 cmd/microservice1/main.go
将通过它期望的相对于 $GOPATH/src
的路径包含库 lib1
,如下所示:
import "github.com/mybiz/project/lib1"
现在,您的代码可以使用 lib1
下文件中声明的包名称访问该包中导出的符号...通常只是:
package lib1
在 cmd/microservice1/main.go
中,通过上面的导入,您可以使用 lib1
符号,如下所示:
lib1.CallMe()
我希望这有助于阐明 Go 的目录结构是如何工作的。
我是这样组织的; mono-repo 每。项目方法。考虑到这些服务密切相关:
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 的引入,我更倾向于第二种选择。
稍后,当您开始第二个 macro/micro/nano-services 项目时,/pkg 文件夹中的许多这些包也将在那里需要。该怎么办? Copy/paste?不!相反,从项目中提取这些包,即日志、指标并制作您自己的工具包。
请记住,如果您使用某种 CI/CD(您确实应该这样做),您可以选择编写放置在项目根目录中的脚本,该脚本将只检测您在存储库中所做的更改,因此只会构建和交付受影响的服务。有几个如何执行此操作的示例。
感谢@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
每个微服务都应该是一个独立的服务,并使用 RESTful、RPC 或消息传递通过网络相互通信。按照 12 Factor of App is a virtue when designing a microservice to make sure it easy to ship. Check typical-go-server 获取有关如何使微服务友好项目的示例。
我正处于在 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 中构建这样的项目的 'correct' 或惯用方法是什么?
如何组织我的项目?
|-- github.com/avelino/service1
|-- Dockerfile
|-- main.go
|-- github.com/avelino/service2
|-- Dockerfile
|-- main.go
|-- github.com/avelino/service3
|-- Dockerfile
|-- main.go
套餐
所有 Go 代码都组织成包。 Go 中的包只是一个 directory/folder,其中包含一个或多个 .go 文件。 Go 包提供代码的隔离和组织,类似于 directories/folders 在计算机上组织文件的方式。
所有 Go 代码都在包中,包是访问 Go 代码的入口点。理解和建立围绕包的良好实践对于编写有效的 Go 代码很重要。
这里的另一个答案提倡将每个微服务放入自己的存储库中。以这种方式拆分东西可能有正当理由,但想要将所有内容都保存在一个存储库中也可能有同样正当的理由(这实际上取决于您的项目/环境)
如果你想将所有代码放在一个存储库中,你可以 - 你只需要遵循 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 工作区中(请参阅我上面分享的 link)。假设您的存储库位于 github.com/mybiz/project,而您的 GOPATH
是 ~/go
,工作区将如下所示:
~/go/src/github.com/mybiz/
-- project/
<clone repo in here>
文件 cmd/microservice1/main.go
将通过它期望的相对于 $GOPATH/src
的路径包含库 lib1
,如下所示:
import "github.com/mybiz/project/lib1"
现在,您的代码可以使用 lib1
下文件中声明的包名称访问该包中导出的符号...通常只是:
package lib1
在 cmd/microservice1/main.go
中,通过上面的导入,您可以使用 lib1
符号,如下所示:
lib1.CallMe()
我希望这有助于阐明 Go 的目录结构是如何工作的。
我是这样组织的; mono-repo 每。项目方法。考虑到这些服务密切相关:
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 的引入,我更倾向于第二种选择。
稍后,当您开始第二个 macro/micro/nano-services 项目时,/pkg 文件夹中的许多这些包也将在那里需要。该怎么办? Copy/paste?不!相反,从项目中提取这些包,即日志、指标并制作您自己的工具包。
请记住,如果您使用某种 CI/CD(您确实应该这样做),您可以选择编写放置在项目根目录中的脚本,该脚本将只检测您在存储库中所做的更改,因此只会构建和交付受影响的服务。有几个如何执行此操作的示例。
感谢@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
每个微服务都应该是一个独立的服务,并使用 RESTful、RPC 或消息传递通过网络相互通信。按照 12 Factor of App is a virtue when designing a microservice to make sure it easy to ship. Check typical-go-server 获取有关如何使微服务友好项目的示例。