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でこのようなプロジェクトを構成する「正しい」または慣用的な方法は何ですか?
ここでの他の答えは、各マイクロサービスを独自のリポジトリに配置することを提唱しています。そのように物事を分割する正当な理由があるかもしれませんが、すべてを1つのリポジトリに保持したいという同様に正当な理由があるかもしれません(それは本当にあなたのプロジェクト/状況に依存します)
1つのリポジトリにすべてのコードが必要な場合は、Goのパッケージルールに従う必要があります。 (これは良い読み物です: https://golang.org/doc/code.html#Workspaces )
コマンドとライブラリが混在している場合は、質問で提案したディレクトリ構造が近くなりますが、おそらくそこにsrc
ディレクトリは必要ありません。ライブラリとコマンドを含むリポジトリ内のディレクトリ構造がどのように見えるかの例を次に示します。
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のディレクトリ構造がどのように機能するかを明確にするのに役立つことを願っています。
私はそれをこのように構成しています。モノレポジトリ。プロジェクトアプローチ。これらのサービスが密接に関連していることを考慮に入れると:
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の導入により、私は2番目の選択肢にさらに傾いています。
後で、2番目のmacro/micro/nano-servicesプロジェクトを開始するときに、/ pkgフォルダー内のこれらのパッケージの多くもそこで必要になります。何をすべきか?コピーペースト?番号!代わりに、これらのパッケージをプロジェクトから抽出します。つまり、ログ、メトリック、および独自のキットを作成します。
ある種の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
プロジェクトを整理するにはどうすればよいですか?
|-- github.com/avelino/service1
|-- Dockerfile
|-- main.go
|-- github.com/avelino/service2
|-- Dockerfile
|-- main.go
|-- github.com/avelino/service3
|-- Dockerfile
|-- main.go
すべてのGoコードはパッケージに編成されています。 Goのパッケージは、1つ以上の.goファイルが含まれている単なるディレクトリ/フォルダです。 Goパッケージは、ディレクトリ/フォルダがコンピュータ上のファイルを整理する方法と同様に、コードの分離と整理を提供します。
すべてのGoコードはパッケージ内にあり、パッケージはGoコードにアクセスするためのエントリポイントです。効果的なGoコードを作成するには、パッケージに関するグッドプラクティスを理解して確立することが重要です。
各マイクロサービスは独立したサービスであり、RESTful、RPC、またはメッセージングのいずれかを使用してネットワークを介して相互に通信する必要があります。フォロー 12 Factor of App マイクロサービスを設計する際のメリットは、出荷が容易であることを確認することです。マイクロサービスに適したプロジェクトを作成する方法の例については、 typical-go-server を確認してください。