我正处于在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中构建像这样的项目的“正确”或惯用方法是什么?
答案 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,获取有关如何进行微服务友好项目的示例。