Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89f3712347 | ||
|
|
af7acdd843 | ||
|
|
7ffa3349a9 | ||
|
|
f03862c378 | ||
|
|
fe3e70a60f | ||
|
|
36174ba5cc | ||
|
|
7b17b3604a | ||
|
|
eb40c2731d | ||
|
|
618bec5075 | ||
|
|
5821b7324e | ||
|
|
befdaab542 | ||
|
|
431be8ed9d | ||
|
|
3c688c319e | ||
|
|
59ffa75c00 | ||
|
|
09340e82a7 |
Binary file not shown.
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 126 KiB |
444
doc/shorturl.md
444
doc/shorturl.md
@@ -1,50 +1,77 @@
|
|||||||
# 使用go-zero从0到1快速构建高并发的短链服务
|
# 快速构建高并发微服务
|
||||||
|
|
||||||
## 0. 什么是短链服务?
|
## 0. 为什么说做好微服务很难?
|
||||||
|
|
||||||
|
要想做好微服务,我们需要理解和掌握的知识点非常多,从几个维度上来说:
|
||||||
|
|
||||||
|
* 基本功能层面
|
||||||
|
1. 并发控制&限流,避免服务被突发流量击垮
|
||||||
|
2. 服务注册与服务发现,确保能够动态侦测增减的节点
|
||||||
|
3. 负载均衡,需要根据节点承受能力分发流量
|
||||||
|
4. 超时控制,避免对已超时请求做无用功
|
||||||
|
5. 熔断设计,快速失败,保障故障节点的恢复能力
|
||||||
|
|
||||||
|
* 高阶功能层面
|
||||||
|
1. 请求认证,确保每个用户只能访问自己的数据
|
||||||
|
2. 链路追踪,用于理解整个系统和快速定位特定请求的问题
|
||||||
|
3. 日志,用于数据收集和问题定位
|
||||||
|
4. 可观测性,没有度量就没有优化
|
||||||
|
|
||||||
|
对于其中每一点,我们都需要用很长的篇幅来讲述其原理和实现,那么对我们后端开发者来说,要想把这些知识点都掌握并落实到业务系统里,难度是非常大的,不过我们可以依赖已经被大流量验证过的框架体系。[go-zero微服务框架](https://github.com/tal-tech/go-zero)就是为此而生。
|
||||||
|
|
||||||
|
另外,我们始终秉承**工具大于约定和文档**的理念。我们希望尽可能减少开发人员的心智负担,把精力都投入到产生业务价值的代码上,减少重复代码的编写,所以我们开发了`goctl`工具。
|
||||||
|
|
||||||
|
下面我通过短链微服务来演示通过[go-zero](https://github.com/tal-tech/go-zero)快速的创建微服务的流程,走完一遍,你就会发现:原来编写微服务如此简单!
|
||||||
|
|
||||||
|
## 1. 什么是短链服务?
|
||||||
|
|
||||||
短链服务就是将长的URL网址,通过程序计算等方式,转换为简短的网址字符串。
|
短链服务就是将长的URL网址,通过程序计算等方式,转换为简短的网址字符串。
|
||||||
|
|
||||||
写此短链服务是为了从整体上演示go-zero构建完整微服务的过程,算法和实现细节尽可能简化了,所以这不是一个高阶的短链服务。
|
写此短链服务是为了从整体上演示go-zero构建完整微服务的过程,算法和实现细节尽可能简化了,所以这不是一个高阶的短链服务。
|
||||||
|
|
||||||
## 1. 短链微服务架构图
|
## 2. 短链微服务架构图
|
||||||
|
|
||||||
<img src="images/shorturl-arch.png" alt="架构图" width="800" />
|
<img src="images/shorturl-arch.png" alt="架构图" width="800" />
|
||||||
|
|
||||||
## 2. 准备工作
|
* 这里只用了`Transform RPC`一个微服务,并不是说API Gateway只能调用一个微服务,只是为了最简演示API Gateway如何调用RPC微服务而已
|
||||||
|
* 在真正项目里要尽可能每个微服务使用自己的数据库,数据边界要清晰
|
||||||
|
|
||||||
|
## 3. 准备工作
|
||||||
|
|
||||||
* 安装etcd, mysql, redis
|
* 安装etcd, mysql, redis
|
||||||
* 准备goctl工具
|
|
||||||
* 直接从`https://github.com/tal-tech/go-zero/releases`下载最新版,后续会加上自动更新
|
* 安装goctl工具
|
||||||
* 也可以从源码编译,在任意目录下进行,目的是为了编译goctl工具
|
|
||||||
|
```shell
|
||||||
1. `git clone https://github.com/tal-tech/go-zero`
|
export GO111MODULE=on export GOPROXY=https://goproxy.cn/,direct go get github.com/tal-tech/go-zero/tools/goctl
|
||||||
2. 在`tools/goctl`目录下编译goctl工具`go build goctl.go`
|
```
|
||||||
3. 将生成的goctl放到`$PATH`下,确保goctl命令可运行
|
|
||||||
* 创建工作目录`shorturl`
|
* 创建工作目录`shorturl`
|
||||||
|
|
||||||
* 在`shorturl`目录下执行`go mod init shorturl`初始化`go.mod`
|
* 在`shorturl`目录下执行`go mod init shorturl`初始化`go.mod`
|
||||||
|
|
||||||
## 3. 编写API Gateway代码
|
## 4. 编写API Gateway代码
|
||||||
|
|
||||||
* 通过goctl生成`shorturl.api`并编辑,为了简洁,去除了文件开头的`info`,代码如下:
|
* 通过goctl生成`api/shorturl.api`并编辑,为了简洁,去除了文件开头的`info`,代码如下:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
type (
|
||||||
|
expandReq struct {
|
||||||
|
shorten string `form:"shorten"`
|
||||||
|
}
|
||||||
|
|
||||||
|
expandResp struct {
|
||||||
|
url string `json:"url"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
shortenReq struct {
|
shortenReq struct {
|
||||||
url string `form:"url"`
|
url string `form:"url"`
|
||||||
}
|
}
|
||||||
|
|
||||||
shortenResp struct {
|
shortenResp struct {
|
||||||
shortUrl string `json:"shortUrl"`
|
shorten string `json:"shorten"`
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
expandReq struct {
|
|
||||||
key string `form:"key"`
|
|
||||||
}
|
|
||||||
|
|
||||||
expandResp struct {
|
|
||||||
url string `json:"url"`
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -71,7 +98,7 @@
|
|||||||
* 使用goctl生成API Gateway代码
|
* 使用goctl生成API Gateway代码
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
goctl api go -api shorturl.api -dir api
|
goctl api go -api shorturl.api -dir .
|
||||||
```
|
```
|
||||||
|
|
||||||
生成的文件结构如下:
|
生成的文件结构如下:
|
||||||
@@ -95,16 +122,16 @@
|
|||||||
│ │ │ └── servicecontext.go // 定义ServiceContext
|
│ │ │ └── servicecontext.go // 定义ServiceContext
|
||||||
│ │ └── types
|
│ │ └── types
|
||||||
│ │ └── types.go // 定义请求、返回结构体
|
│ │ └── types.go // 定义请求、返回结构体
|
||||||
|
│ ├── shorturl.api
|
||||||
│ └── shorturl.go // main入口定义
|
│ └── shorturl.go // main入口定义
|
||||||
├── go.mod
|
├── go.mod
|
||||||
├── go.sum
|
└── go.sum
|
||||||
└── shorturl.api
|
|
||||||
```
|
```
|
||||||
|
|
||||||
* 启动API Gateway服务,默认侦听在8888端口
|
* 启动API Gateway服务,默认侦听在8888端口
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
go run api/shorturl.go -f api/etc/shorturl-api.yaml
|
go run shorturl.go -f etc/shorturl-api.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
* 测试API Gateway服务
|
* 测试API Gateway服务
|
||||||
@@ -134,14 +161,14 @@
|
|||||||
|
|
||||||
* 到这里,你已经可以通过goctl生成客户端代码给客户端同学并行开发了,支持多种语言,详见文档
|
* 到这里,你已经可以通过goctl生成客户端代码给客户端同学并行开发了,支持多种语言,详见文档
|
||||||
|
|
||||||
## 4. 编写shorten rpc服务
|
## 5. 编写transform rpc服务
|
||||||
|
|
||||||
* 在`rpc/shorten`目录下编写`shorten.proto`文件
|
* 在`rpc/transform`目录下编写`transform.proto`文件
|
||||||
|
|
||||||
可以通过命令生成proto文件模板
|
可以通过命令生成proto文件模板
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
goctl rpc template -o shorten.proto
|
goctl rpc template -o transform.proto
|
||||||
```
|
```
|
||||||
|
|
||||||
修改后文件内容如下:
|
修改后文件内容如下:
|
||||||
@@ -149,183 +176,120 @@
|
|||||||
```protobuf
|
```protobuf
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
package shorten;
|
package transform;
|
||||||
|
|
||||||
message shortenReq {
|
|
||||||
string url = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message shortenResp {
|
|
||||||
string key = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
service shortener {
|
|
||||||
rpc shorten(shortenReq) returns(shortenResp);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
* 用`goctl`生成rpc代码,在`rpc/shorten`目录下执行命令
|
|
||||||
|
|
||||||
```shell
|
|
||||||
goctl rpc proto -src shorten.proto
|
|
||||||
```
|
|
||||||
|
|
||||||
文件结构如下:
|
|
||||||
|
|
||||||
```
|
|
||||||
rpc/shorten
|
|
||||||
├── etc
|
|
||||||
│ └── shorten.yaml // 配置文件
|
|
||||||
├── internal
|
|
||||||
│ ├── config
|
|
||||||
│ │ └── config.go // 配置定义
|
|
||||||
│ ├── logic
|
|
||||||
│ │ └── shortenlogic.go // rpc业务逻辑在这里实现
|
|
||||||
│ ├── server
|
|
||||||
│ │ └── shortenerserver.go // 调用入口, 不需要修改
|
|
||||||
│ └── svc
|
|
||||||
│ └── servicecontext.go // 定义ServiceContext,传递依赖
|
|
||||||
├── pb
|
|
||||||
│ └── shorten.pb.go
|
|
||||||
├── shorten.go // rpc服务main函数
|
|
||||||
├── shorten.proto
|
|
||||||
└── shortener
|
|
||||||
├── shortener.go // 提供了外部调用方法,无需修改
|
|
||||||
├── shortener_mock.go // mock方法,测试用
|
|
||||||
└── types.go // request/response结构体定义
|
|
||||||
```
|
|
||||||
|
|
||||||
直接可以运行,如下:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
$ go run shorten.go -f etc/shorten.yaml
|
|
||||||
Starting rpc server at 127.0.0.1:8080...
|
|
||||||
```
|
|
||||||
|
|
||||||
`etc/shorten.yaml`文件里可以修改侦听端口等配置
|
|
||||||
|
|
||||||
## 5. 编写expand rpc服务
|
|
||||||
|
|
||||||
* 在`rpc/expand`目录下编写`expand.proto`文件
|
|
||||||
|
|
||||||
可以通过命令生成proto文件模板
|
|
||||||
|
|
||||||
```shell
|
|
||||||
goctl rpc template -o expand.proto
|
|
||||||
```
|
|
||||||
|
|
||||||
修改后文件内容如下:
|
|
||||||
|
|
||||||
```protobuf
|
|
||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package expand;
|
|
||||||
|
|
||||||
message expandReq {
|
message expandReq {
|
||||||
string key = 1;
|
string shorten = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message expandResp {
|
message expandResp {
|
||||||
string url = 1;
|
string url = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
service expander {
|
message shortenReq {
|
||||||
|
string url = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message shortenResp {
|
||||||
|
string shorten = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
service transformer {
|
||||||
rpc expand(expandReq) returns(expandResp);
|
rpc expand(expandReq) returns(expandResp);
|
||||||
|
rpc shorten(shortenReq) returns(shortenResp);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
* 用`goctl`生成rpc代码,在`rpc/expand`目录下执行命令
|
* 用`goctl`生成rpc代码,在`rpc/transform`目录下执行命令
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
goctl rpc proto -src expand.proto
|
goctl rpc proto -src transform.proto
|
||||||
```
|
```
|
||||||
|
|
||||||
文件结构如下:
|
文件结构如下:
|
||||||
|
|
||||||
```
|
```
|
||||||
rpc/expand
|
rpc/transform
|
||||||
├── etc
|
├── etc
|
||||||
│ └── expand.yaml // 配置文件
|
│ └── transform.yaml // 配置文件
|
||||||
├── expand.go // rpc服务main函数
|
|
||||||
├── expand.proto
|
|
||||||
├── expander
|
|
||||||
│ ├── expander.go // 提供了外部调用方法,无需修改
|
|
||||||
│ ├── expander_mock.go // mock方法,测试用
|
|
||||||
│ └── types.go // request/response结构体定义
|
|
||||||
├── internal
|
├── internal
|
||||||
│ ├── config
|
│ ├── config
|
||||||
│ │ └── config.go // 配置定义
|
│ │ └── config.go // 配置定义
|
||||||
│ ├── logic
|
│ ├── logic
|
||||||
│ │ └── expandlogic.go // rpc业务逻辑在这里实现
|
│ │ ├── expandlogic.go // expand业务逻辑在这里实现
|
||||||
|
│ │ └── shortenlogic.go // shorten业务逻辑在这里实现
|
||||||
│ ├── server
|
│ ├── server
|
||||||
│ │ └── expanderserver.go // 调用入口, 不需要修改
|
│ │ └── transformerserver.go // 调用入口, 不需要修改
|
||||||
│ └── svc
|
│ └── svc
|
||||||
│ └── servicecontext.go // 定义ServiceContext,传递依赖
|
│ └── servicecontext.go // 定义ServiceContext,传递依赖
|
||||||
└── pb
|
├── pb
|
||||||
└── expand.pb.go
|
│ └── transform.pb.go
|
||||||
|
├── transform.go // rpc服务main函数
|
||||||
|
├── transform.proto
|
||||||
|
└── transformer
|
||||||
|
├── transformer.go // 提供了外部调用方法,无需修改
|
||||||
|
├── transformer_mock.go // mock方法,测试用
|
||||||
|
└── types.go // request/response结构体定义
|
||||||
```
|
```
|
||||||
|
|
||||||
修改`etc/expand.yaml`里面的`ListenOn`的端口为`8081`,因为`8080`已经被`shorten`服务占用了
|
直接可以运行,如下:
|
||||||
|
|
||||||
修改后运行,如下:
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ go run expand.go -f etc/expand.yaml
|
$ go run transform.go -f etc/transform.yaml
|
||||||
Starting rpc server at 127.0.0.1:8081...
|
Starting rpc server at 127.0.0.1:8080...
|
||||||
```
|
```
|
||||||
|
|
||||||
`etc/expand.yaml`文件里可以修改侦听端口等配置
|
|
||||||
|
|
||||||
## 6. 修改API Gateway代码调用shorten/expand rpc服务
|
`etc/transform.yaml`文件里可以修改侦听端口等配置
|
||||||
|
|
||||||
* 修改配置文件`shorter-api.yaml`,增加如下内容
|
## 6. 修改API Gateway代码调用transform rpc服务
|
||||||
|
|
||||||
|
* 修改配置文件`shorturl-api.yaml`,增加如下内容
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
Shortener:
|
Transform:
|
||||||
Etcd:
|
Etcd:
|
||||||
Hosts:
|
Hosts:
|
||||||
- localhost:2379
|
- localhost:2379
|
||||||
Key: shorten.rpc
|
Key: transform.rpc
|
||||||
Expander:
|
|
||||||
Etcd:
|
|
||||||
Hosts:
|
|
||||||
- localhost:2379
|
|
||||||
Key: expand.rpc
|
|
||||||
```
|
```
|
||||||
|
|
||||||
通过etcd自动去发现可用的shorten/expand服务
|
通过etcd自动去发现可用的transform服务
|
||||||
|
|
||||||
* 修改`internal/config/config.go`如下,增加shorten/expand服务依赖
|
* 修改`internal/config/config.go`如下,增加transform服务依赖
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type Config struct {
|
type Config struct {
|
||||||
rest.RestConf
|
rest.RestConf
|
||||||
Shortener rpcx.RpcClientConf // 手动代码
|
Transform rpcx.RpcClientConf // 手动代码
|
||||||
Expander rpcx.RpcClientConf // 手动代码
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
* 修改`internal/logic/expandlogic.go`,如下:
|
* 修改`internal/svc/servicecontext.go`,如下:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type ExpandLogic struct {
|
type ServiceContext struct {
|
||||||
ctx context.Context
|
Config config.Config
|
||||||
logx.Logger
|
Transformer rpcx.Client // 手动代码
|
||||||
expander rpcx.Client // 手动代码
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewExpandLogic(ctx context.Context, svcCtx *svc.ServiceContext) ExpandLogic {
|
func NewServiceContext(c config.Config) *ServiceContext {
|
||||||
return ExpandLogic{
|
return &ServiceContext{
|
||||||
ctx: ctx,
|
Config: c,
|
||||||
Logger: logx.WithContext(ctx),
|
Transformer: rpcx.MustNewClient(c.Transform), // 手动代码
|
||||||
expander: svcCtx.Expander, // 手动代码
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
通过ServiceContext在不同业务逻辑之间传递依赖
|
||||||
|
|
||||||
|
* 修改`internal/logic/expandlogic.go`里的`Expand`方法,如下:
|
||||||
|
|
||||||
|
```go
|
||||||
func (l *ExpandLogic) Expand(req types.ExpandReq) (*types.ExpandResp, error) {
|
func (l *ExpandLogic) Expand(req types.ExpandReq) (*types.ExpandResp, error) {
|
||||||
// 手动代码开始
|
// 手动代码开始
|
||||||
resp, err := expander.NewExpander(l.expander).Expand(l.ctx, &expander.ExpandReq{
|
trans := transformer.NewTransformer(l.svcCtx.Transformer)
|
||||||
Key: req.Key,
|
resp, err := trans.Expand(l.ctx, &transformer.ExpandReq{
|
||||||
|
Shorten: req.Shorten,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -338,28 +302,15 @@
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
增加了对`expander`服务的依赖,并通过调用`expander`的`Expand`方法实现短链恢复到url
|
通过调用`transformer`的`Expand`方法实现短链恢复到url
|
||||||
|
|
||||||
* 修改`internal/logic/shortenlogic.go`,如下:
|
* 修改`internal/logic/shortenlogic.go`,如下:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type ShortenLogic struct {
|
|
||||||
ctx context.Context
|
|
||||||
logx.Logger
|
|
||||||
shortener rpcx.Client // 手动代码
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewShortenLogic(ctx context.Context, svcCtx *svc.ServiceContext) ShortenLogic {
|
|
||||||
return ShortenLogic{
|
|
||||||
ctx: ctx,
|
|
||||||
Logger: logx.WithContext(ctx),
|
|
||||||
shortener: svcCtx.Shortener, // 手动代码
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *ShortenLogic) Shorten(req types.ShortenReq) (*types.ShortenResp, error) {
|
func (l *ShortenLogic) Shorten(req types.ShortenReq) (*types.ShortenResp, error) {
|
||||||
// 手动代码开始
|
// 手动代码开始
|
||||||
resp, err := shortener.NewShortener(l.shortener).Shorten(l.ctx, &shortener.ShortenReq{
|
trans := transformer.NewTransformer(l.svcCtx.Transformer)
|
||||||
|
resp, err := trans.Shorten(l.ctx, &transformer.ShortenReq{
|
||||||
Url: req.Url,
|
Url: req.Url,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -367,49 +318,28 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &types.ShortenResp{
|
return &types.ShortenResp{
|
||||||
ShortUrl: resp.Key,
|
Shorten: resp.Shorten,
|
||||||
}, nil
|
}, nil
|
||||||
// 手动代码结束
|
// 手动代码结束
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
增加了对`shortener`服务的依赖,并通过调用`shortener`的`Shorten`方法实现url到短链的变换
|
通过调用`transformer`的`Shorten`方法实现url到短链的变换
|
||||||
|
|
||||||
* 修改`internal/svc/servicecontext.go`,如下:
|
|
||||||
|
|
||||||
```go
|
|
||||||
type ServiceContext struct {
|
|
||||||
Config config.Config
|
|
||||||
Shortener rpcx.Client // 手动代码
|
|
||||||
Expander rpcx.Client // 手动代码
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewServiceContext(config config.Config) *ServiceContext {
|
|
||||||
return &ServiceContext{
|
|
||||||
Config: config,
|
|
||||||
Shortener: rpcx.MustNewClient(config.Shortener), // 手动代码
|
|
||||||
Expander: rpcx.MustNewClient(config.Expander), // 手动代码
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
通过ServiceContext在不同业务逻辑之间传递依赖
|
|
||||||
|
|
||||||
至此,API Gateway修改完成,虽然贴的代码多,但是期中修改的是很少的一部分,为了方便理解上下文,我贴了完整代码,接下来处理CRUD+cache
|
至此,API Gateway修改完成,虽然贴的代码多,但是期中修改的是很少的一部分,为了方便理解上下文,我贴了完整代码,接下来处理CRUD+cache
|
||||||
|
|
||||||
## 7. 定义数据库表结构,并生成CRUD+cache代码
|
## 7. 定义数据库表结构,并生成CRUD+cache代码
|
||||||
|
|
||||||
* shorturl下创建rpc/model目录:`mkdir -p rpc/model`
|
* shorturl下创建`rpc/transform/model`目录:`mkdir -p rpc/transform/model`
|
||||||
* 在roc/model目录下编写创建shorturl表的sql文件`shorturl.sql`,如下:
|
|
||||||
|
* 在rpc/transform/model目录下编写创建shorturl表的sql文件`shorturl.sql`,如下:
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
CREATE TABLE `shorturl`
|
CREATE TABLE `shorturl`
|
||||||
(
|
(
|
||||||
`id` bigint(10) NOT NULL AUTO_INCREMENT,
|
`shorten` varchar(255) NOT NULL COMMENT 'shorten key',
|
||||||
`key` varchar(255) NOT NULL DEFAULT '' COMMENT 'shorten key',
|
`url` varchar(255) NOT NULL COMMENT 'original url',
|
||||||
`url` varchar(255) DEFAULT '' COMMENT 'original url',
|
PRIMARY KEY(`shorten`)
|
||||||
PRIMARY KEY(`id`),
|
|
||||||
UNIQUE KEY `key_index`(`key`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -423,18 +353,18 @@
|
|||||||
source shorturl.sql;
|
source shorturl.sql;
|
||||||
```
|
```
|
||||||
|
|
||||||
* 在`rpc/model`目录下执行如下命令生成CRUD+cache代码,`-c`表示使用`redis cache`
|
* 在`rpc/transform/model`目录下执行如下命令生成CRUD+cache代码,`-c`表示使用`redis cache`
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
goctl model mysql ddl -c -src shorturl.sql -dir .
|
goctl model mysql ddl -c -src shorturl.sql -dir .
|
||||||
```
|
```
|
||||||
|
|
||||||
也可以用`datasource`命令代替`ddl`来指定数据库链接直接从schema生成
|
也可以用`datasource`命令代替`ddl`来指定数据库链接直接从schema生成
|
||||||
|
|
||||||
生成后的文件结构如下:
|
生成后的文件结构如下:
|
||||||
|
|
||||||
```
|
```
|
||||||
rpc/model
|
rpc/transform/model
|
||||||
├── shorturl.sql
|
├── shorturl.sql
|
||||||
├── shorturlmodel.go // CRUD+cache代码
|
├── shorturlmodel.go // CRUD+cache代码
|
||||||
└── vars.go // 定义常量和变量
|
└── vars.go // 定义常量和变量
|
||||||
@@ -442,7 +372,7 @@
|
|||||||
|
|
||||||
## 8. 修改shorten/expand rpc代码调用crud+cache代码
|
## 8. 修改shorten/expand rpc代码调用crud+cache代码
|
||||||
|
|
||||||
* 修改`rpc/expand/etc/expand.yaml`,增加如下内容:
|
* 修改`rpc/transform/etc/transform.yaml`,增加如下内容:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
DataSource: root:@tcp(localhost:3306)/gozero
|
DataSource: root:@tcp(localhost:3306)/gozero
|
||||||
@@ -453,7 +383,7 @@
|
|||||||
|
|
||||||
可以使用多个redis作为cache,支持redis单点或者redis集群
|
可以使用多个redis作为cache,支持redis单点或者redis集群
|
||||||
|
|
||||||
* 修改`rpc/expand/internal/config.go`,如下:
|
* 修改`rpc/transform/internal/config.go`,如下:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type Config struct {
|
type Config struct {
|
||||||
@@ -466,116 +396,46 @@
|
|||||||
|
|
||||||
增加了mysql和redis cache配置
|
增加了mysql和redis cache配置
|
||||||
|
|
||||||
* 修改`rpc/expand/internal/svc/servicecontext.go`,如下:
|
* 修改`rpc/transform/internal/svc/servicecontext.go`,如下:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type ServiceContext struct {
|
type ServiceContext struct {
|
||||||
c config.Config
|
c config.Config
|
||||||
Model *model.ShorturlModel // 手动代码
|
Model *model.ShorturlModel // 手动代码
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServiceContext(c config.Config) *ServiceContext {
|
func NewServiceContext(c config.Config) *ServiceContext {
|
||||||
return &ServiceContext{
|
return &ServiceContext{
|
||||||
c: c,
|
c: c,
|
||||||
Model: model.NewShorturlModel(sqlx.NewMysql(c.DataSource), c.Cache, c.Table), // 手动代码
|
Model: model.NewShorturlModel(sqlx.NewMysql(c.DataSource), c.Cache, c.Table), // 手动代码
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
* 修改`rpc/expand/internal/logic/expandlogic.go`,如下:
|
* 修改`rpc/transform/internal/logic/expandlogic.go`,如下:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type ExpandLogic struct {
|
|
||||||
ctx context.Context
|
|
||||||
logx.Logger
|
|
||||||
model *model.ShorturlModel // 手动代码
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewExpandLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ExpandLogic {
|
|
||||||
return &ExpandLogic{
|
|
||||||
ctx: ctx,
|
|
||||||
Logger: logx.WithContext(ctx),
|
|
||||||
model: svcCtx.Model, // 手动代码
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *ExpandLogic) Expand(in *expand.ExpandReq) (*expand.ExpandResp, error) {
|
func (l *ExpandLogic) Expand(in *expand.ExpandReq) (*expand.ExpandResp, error) {
|
||||||
// 手动代码开始
|
// 手动代码开始
|
||||||
res, err := l.model.FindOne(in.Key)
|
res, err := l.svcCtx.Model.FindOne(in.Shorten)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &expand.ExpandResp{
|
return &transform.ExpandResp{
|
||||||
Url: res.Url,
|
Url: res.Url,
|
||||||
}, nil
|
}, nil
|
||||||
// 手动代码结束
|
// 手动代码结束
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
* 修改`rpc/shorten/etc/shorten.yaml`,增加如下内容:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
DataSource: root:@tcp(localhost:3306)/gozero
|
|
||||||
Table: shorturl
|
|
||||||
Cache:
|
|
||||||
- Host: localhost:6379
|
|
||||||
```
|
|
||||||
|
|
||||||
可以使用多个redis作为cache,支持redis单点或者redis集群
|
|
||||||
|
|
||||||
* 修改`rpc/shorten/internal/config.go`,如下:
|
|
||||||
|
|
||||||
```go
|
|
||||||
type Config struct {
|
|
||||||
rpcx.RpcServerConf
|
|
||||||
DataSource string // 手动代码
|
|
||||||
Table string // 手动代码
|
|
||||||
Cache cache.CacheConf // 手动代码
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
增加了mysql和redis cache配置
|
|
||||||
|
|
||||||
* 修改`rpc/shorten/internal/svc/servicecontext.go`,如下:
|
|
||||||
|
|
||||||
```go
|
|
||||||
type ServiceContext struct {
|
|
||||||
c config.Config
|
|
||||||
Model *model.ShorturlModel // 手动代码
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewServiceContext(c config.Config) *ServiceContext {
|
|
||||||
return &ServiceContext{
|
|
||||||
c: c,
|
|
||||||
Model: model.NewShorturlModel(sqlx.NewMysql(c.DataSource), c.Cache, c.Table), // 手动代码
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
* 修改`rpc/shorten/internal/logic/shortenlogic.go`,如下:
|
* 修改`rpc/shorten/internal/logic/shortenlogic.go`,如下:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
const keyLen = 6
|
|
||||||
|
|
||||||
type ShortenLogic struct {
|
|
||||||
ctx context.Context
|
|
||||||
logx.Logger
|
|
||||||
model *model.ShorturlModel // 手动代码
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewShortenLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ShortenLogic {
|
|
||||||
return &ShortenLogic{
|
|
||||||
ctx: ctx,
|
|
||||||
Logger: logx.WithContext(ctx),
|
|
||||||
model: svcCtx.Model, // 手动代码
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *ShortenLogic) Shorten(in *shorten.ShortenReq) (*shorten.ShortenResp, error) {
|
func (l *ShortenLogic) Shorten(in *shorten.ShortenReq) (*shorten.ShortenResp, error) {
|
||||||
// 手动代码开始,生成短链接
|
// 手动代码开始,生成短链接
|
||||||
key := hash.Md5Hex([]byte(in.Url))[:keyLen]
|
key := hash.Md5Hex([]byte(in.Url))[:6]
|
||||||
_, err := l.model.Insert(model.Shorturl{
|
_, err := l.svcCtx.Model.Insert(model.Shorturl{
|
||||||
Shorten: key,
|
Shorten: key,
|
||||||
Url: in.Url,
|
Url: in.Url,
|
||||||
})
|
})
|
||||||
@@ -583,8 +443,8 @@
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &shorten.ShortenResp{
|
return &transform.ShortenResp{
|
||||||
Key: key,
|
Shorten: key,
|
||||||
}, nil
|
}, nil
|
||||||
// 手动代码结束
|
// 手动代码结束
|
||||||
}
|
}
|
||||||
@@ -597,7 +457,7 @@
|
|||||||
* shorten api调用
|
* shorten api调用
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
~ curl -i "http://localhost:8888/shorten?url=http://www.xiaoheiban.cn"
|
curl -i "http://localhost:8888/shorten?url=http://www.xiaoheiban.cn"
|
||||||
```
|
```
|
||||||
|
|
||||||
返回如下:
|
返回如下:
|
||||||
@@ -608,13 +468,13 @@
|
|||||||
Date: Sat, 29 Aug 2020 10:49:49 GMT
|
Date: Sat, 29 Aug 2020 10:49:49 GMT
|
||||||
Content-Length: 21
|
Content-Length: 21
|
||||||
|
|
||||||
{"shortUrl":"f35b2a"}
|
{"shorten":"f35b2a"}
|
||||||
```
|
```
|
||||||
|
|
||||||
* expand api调用
|
* expand api调用
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl -i "http://localhost:8888/expand?key=f35b2a"
|
curl -i "http://localhost:8888/expand?shorten=f35b2a"
|
||||||
```
|
```
|
||||||
|
|
||||||
返回如下:
|
返回如下:
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
version := v$(shell /bin/date "+%y%m%d%H%M%S")
|
|
||||||
|
|
||||||
build:
|
|
||||||
#docker pull alpine
|
|
||||||
#docker pull golang:alpine
|
|
||||||
cd $(GOPATH)/src/zero && docker build -t registry.cn-hangzhou.aliyuncs.com/xapp/etcdmon:$(version) . -f example/etcd/demo/Dockerfile
|
|
||||||
#docker image prune --filter label=stage=gobuilder -f
|
|
||||||
|
|
||||||
push: build
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/xapp/etcdmon:$(version)
|
|
||||||
|
|
||||||
deploy: push
|
|
||||||
kubectl -n xx-xiaoheiban set image deployment/etcdmon-deployment etcdmon=registry-vpc.cn-hangzhou.aliyuncs.com/xapp/etcdmon:$(version)
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: etcdmon
|
|
||||||
namespace: discov
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: etcdmon
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/etcdmon:v200620093045
|
|
||||||
imagePullPolicy: Always
|
|
||||||
env:
|
|
||||||
- name: ETCD_CLUSTER
|
|
||||||
value: etcd.discov:2379
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: discovery
|
|
||||||
@@ -1,378 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: discov
|
|
||||||
namespace: discovery
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- name: discov-port
|
|
||||||
port: 2379
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 2379
|
|
||||||
selector:
|
|
||||||
app: discov
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: discov
|
|
||||||
discov_node: discov0
|
|
||||||
name: discov0
|
|
||||||
namespace: discovery
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- command:
|
|
||||||
- /usr/local/bin/etcd
|
|
||||||
- --name
|
|
||||||
- discov0
|
|
||||||
- --initial-advertise-peer-urls
|
|
||||||
- http://discov0:2380
|
|
||||||
- --listen-peer-urls
|
|
||||||
- http://0.0.0.0:2380
|
|
||||||
- --listen-client-urls
|
|
||||||
- http://0.0.0.0:2379
|
|
||||||
- --advertise-client-urls
|
|
||||||
- http://discov0:2379
|
|
||||||
- --initial-cluster
|
|
||||||
- discov0=http://discov0:2380,discov1=http://discov1:2380,discov2=http://discov2:2380,discov3=http://discov3:2380,discov4=http://discov4:2380
|
|
||||||
- --initial-cluster-state
|
|
||||||
- new
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/etcd:latest
|
|
||||||
name: discov0
|
|
||||||
ports:
|
|
||||||
- containerPort: 2379
|
|
||||||
name: client
|
|
||||||
protocol: TCP
|
|
||||||
- containerPort: 2380
|
|
||||||
name: server
|
|
||||||
protocol: TCP
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
affinity:
|
|
||||||
podAntiAffinity:
|
|
||||||
requiredDuringSchedulingIgnoredDuringExecution:
|
|
||||||
- labelSelector:
|
|
||||||
matchExpressions:
|
|
||||||
- key: app
|
|
||||||
operator: In
|
|
||||||
values:
|
|
||||||
- discov
|
|
||||||
topologyKey: "kubernetes.io/hostname"
|
|
||||||
restartPolicy: Always
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
discov_node: discov0
|
|
||||||
name: discov0
|
|
||||||
namespace: discovery
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- name: client
|
|
||||||
port: 2379
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 2379
|
|
||||||
- name: server
|
|
||||||
port: 2380
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 2380
|
|
||||||
selector:
|
|
||||||
discov_node: discov0
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: discov
|
|
||||||
discov_node: discov1
|
|
||||||
name: discov1
|
|
||||||
namespace: discovery
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- command:
|
|
||||||
- /usr/local/bin/etcd
|
|
||||||
- --name
|
|
||||||
- discov1
|
|
||||||
- --initial-advertise-peer-urls
|
|
||||||
- http://discov1:2380
|
|
||||||
- --listen-peer-urls
|
|
||||||
- http://0.0.0.0:2380
|
|
||||||
- --listen-client-urls
|
|
||||||
- http://0.0.0.0:2379
|
|
||||||
- --advertise-client-urls
|
|
||||||
- http://discov1:2379
|
|
||||||
- --initial-cluster
|
|
||||||
- discov0=http://discov0:2380,discov1=http://discov1:2380,discov2=http://discov2:2380,discov3=http://discov3:2380,discov4=http://discov4:2380
|
|
||||||
- --initial-cluster-state
|
|
||||||
- new
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/etcd:latest
|
|
||||||
name: discov1
|
|
||||||
ports:
|
|
||||||
- containerPort: 2379
|
|
||||||
name: client
|
|
||||||
protocol: TCP
|
|
||||||
- containerPort: 2380
|
|
||||||
name: server
|
|
||||||
protocol: TCP
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
affinity:
|
|
||||||
podAntiAffinity:
|
|
||||||
requiredDuringSchedulingIgnoredDuringExecution:
|
|
||||||
- labelSelector:
|
|
||||||
matchExpressions:
|
|
||||||
- key: app
|
|
||||||
operator: In
|
|
||||||
values:
|
|
||||||
- discov
|
|
||||||
topologyKey: "kubernetes.io/hostname"
|
|
||||||
restartPolicy: Always
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
discov_node: discov1
|
|
||||||
name: discov1
|
|
||||||
namespace: discovery
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- name: client
|
|
||||||
port: 2379
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 2379
|
|
||||||
- name: server
|
|
||||||
port: 2380
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 2380
|
|
||||||
selector:
|
|
||||||
discov_node: discov1
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: discov
|
|
||||||
discov_node: discov2
|
|
||||||
name: discov2
|
|
||||||
namespace: discovery
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- command:
|
|
||||||
- /usr/local/bin/etcd
|
|
||||||
- --name
|
|
||||||
- discov2
|
|
||||||
- --initial-advertise-peer-urls
|
|
||||||
- http://discov2:2380
|
|
||||||
- --listen-peer-urls
|
|
||||||
- http://0.0.0.0:2380
|
|
||||||
- --listen-client-urls
|
|
||||||
- http://0.0.0.0:2379
|
|
||||||
- --advertise-client-urls
|
|
||||||
- http://discov2:2379
|
|
||||||
- --initial-cluster
|
|
||||||
- discov0=http://discov0:2380,discov1=http://discov1:2380,discov2=http://discov2:2380,discov3=http://discov3:2380,discov4=http://discov4:2380
|
|
||||||
- --initial-cluster-state
|
|
||||||
- new
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/etcd:latest
|
|
||||||
name: discov2
|
|
||||||
ports:
|
|
||||||
- containerPort: 2379
|
|
||||||
name: client
|
|
||||||
protocol: TCP
|
|
||||||
- containerPort: 2380
|
|
||||||
name: server
|
|
||||||
protocol: TCP
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
affinity:
|
|
||||||
podAntiAffinity:
|
|
||||||
requiredDuringSchedulingIgnoredDuringExecution:
|
|
||||||
- labelSelector:
|
|
||||||
matchExpressions:
|
|
||||||
- key: app
|
|
||||||
operator: In
|
|
||||||
values:
|
|
||||||
- discov
|
|
||||||
topologyKey: "kubernetes.io/hostname"
|
|
||||||
restartPolicy: Always
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
discov_node: discov2
|
|
||||||
name: discov2
|
|
||||||
namespace: discovery
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- name: client
|
|
||||||
port: 2379
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 2379
|
|
||||||
- name: server
|
|
||||||
port: 2380
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 2380
|
|
||||||
selector:
|
|
||||||
discov_node: discov2
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: discov
|
|
||||||
discov_node: discov3
|
|
||||||
name: discov3
|
|
||||||
namespace: discovery
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- command:
|
|
||||||
- /usr/local/bin/etcd
|
|
||||||
- --name
|
|
||||||
- discov3
|
|
||||||
- --initial-advertise-peer-urls
|
|
||||||
- http://discov3:2380
|
|
||||||
- --listen-peer-urls
|
|
||||||
- http://0.0.0.0:2380
|
|
||||||
- --listen-client-urls
|
|
||||||
- http://0.0.0.0:2379
|
|
||||||
- --advertise-client-urls
|
|
||||||
- http://discov3:2379
|
|
||||||
- --initial-cluster
|
|
||||||
- discov0=http://discov0:2380,discov1=http://discov1:2380,discov2=http://discov2:2380,discov3=http://discov3:2380,discov4=http://discov4:2380
|
|
||||||
- --initial-cluster-state
|
|
||||||
- new
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/etcd:latest
|
|
||||||
name: discov3
|
|
||||||
ports:
|
|
||||||
- containerPort: 2379
|
|
||||||
name: client
|
|
||||||
protocol: TCP
|
|
||||||
- containerPort: 2380
|
|
||||||
name: server
|
|
||||||
protocol: TCP
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
affinity:
|
|
||||||
podAntiAffinity:
|
|
||||||
requiredDuringSchedulingIgnoredDuringExecution:
|
|
||||||
- labelSelector:
|
|
||||||
matchExpressions:
|
|
||||||
- key: app
|
|
||||||
operator: In
|
|
||||||
values:
|
|
||||||
- discov
|
|
||||||
topologyKey: "kubernetes.io/hostname"
|
|
||||||
restartPolicy: Always
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
discov_node: discov3
|
|
||||||
name: discov3
|
|
||||||
namespace: discovery
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- name: client
|
|
||||||
port: 2379
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 2379
|
|
||||||
- name: server
|
|
||||||
port: 2380
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 2380
|
|
||||||
selector:
|
|
||||||
discov_node: discov3
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: discov
|
|
||||||
discov_node: discov4
|
|
||||||
name: discov4
|
|
||||||
namespace: discovery
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- command:
|
|
||||||
- /usr/local/bin/etcd
|
|
||||||
- --name
|
|
||||||
- discov4
|
|
||||||
- --initial-advertise-peer-urls
|
|
||||||
- http://discov4:2380
|
|
||||||
- --listen-peer-urls
|
|
||||||
- http://0.0.0.0:2380
|
|
||||||
- --listen-client-urls
|
|
||||||
- http://0.0.0.0:2379
|
|
||||||
- --advertise-client-urls
|
|
||||||
- http://discov4:2379
|
|
||||||
- --initial-cluster
|
|
||||||
- discov0=http://discov0:2380,discov1=http://discov1:2380,discov2=http://discov2:2380,discov3=http://discov3:2380,discov4=http://discov4:2380
|
|
||||||
- --initial-cluster-state
|
|
||||||
- new
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/etcd:latest
|
|
||||||
name: discov4
|
|
||||||
ports:
|
|
||||||
- containerPort: 2379
|
|
||||||
name: client
|
|
||||||
protocol: TCP
|
|
||||||
- containerPort: 2380
|
|
||||||
name: server
|
|
||||||
protocol: TCP
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
affinity:
|
|
||||||
podAntiAffinity:
|
|
||||||
requiredDuringSchedulingIgnoredDuringExecution:
|
|
||||||
- labelSelector:
|
|
||||||
matchExpressions:
|
|
||||||
- key: app
|
|
||||||
operator: In
|
|
||||||
values:
|
|
||||||
- discov
|
|
||||||
topologyKey: "kubernetes.io/hostname"
|
|
||||||
restartPolicy: Always
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
discov_node: discov4
|
|
||||||
name: discov4
|
|
||||||
namespace: discovery
|
|
||||||
spec:
|
|
||||||
ports:
|
|
||||||
- name: client
|
|
||||||
port: 2379
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 2379
|
|
||||||
- name: server
|
|
||||||
port: 2380
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 2380
|
|
||||||
selector:
|
|
||||||
discov_node: discov4
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
version := v$(shell /bin/date "+%y%m%d%H%M%S")
|
|
||||||
|
|
||||||
build:
|
|
||||||
cd $(GOPATH)/src/zero && docker build -t registry.cn-hangzhou.aliyuncs.com/xapp/pub:$(version) . -f example/etcd/pub/Dockerfile
|
|
||||||
docker image prune --filter label=stage=gobuilder -f
|
|
||||||
|
|
||||||
push: build
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/xapp/pub:$(version)
|
|
||||||
|
|
||||||
deploy: push
|
|
||||||
kubectl -n adhoc set image deployment/pub-deployment pub=registry-vpc.cn-hangzhou.aliyuncs.com/xapp/pub:$(version)
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: pub-deployment
|
|
||||||
namespace: adhoc
|
|
||||||
labels:
|
|
||||||
app: pub
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: pub
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: pub
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: pub
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/pub:v200213172101
|
|
||||||
command:
|
|
||||||
- /app/pub
|
|
||||||
- -v
|
|
||||||
- ccc
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
version := v$(shell /bin/date "+%y%m%d%H%M%S")
|
|
||||||
|
|
||||||
build:
|
|
||||||
cd $(GOPATH)/src/zero && docker build -t registry.cn-hangzhou.aliyuncs.com/xapp/sub:$(version) . -f example/etcd/sub/Dockerfile
|
|
||||||
docker image prune --filter label=stage=gobuilder -f
|
|
||||||
|
|
||||||
push: build
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/xapp/sub:$(version)
|
|
||||||
|
|
||||||
deploy: push
|
|
||||||
kubectl -n adhoc set image deployment/sub-deployment sub=registry-vpc.cn-hangzhou.aliyuncs.com/xapp/sub:$(version)
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: sub
|
|
||||||
name: sub
|
|
||||||
namespace: adhoc
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- command:
|
|
||||||
- /app/sub
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/sub:v200213220509
|
|
||||||
name: sub
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
restartPolicy: Always
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
version := v$(shell /bin/date "+%y%m%d%H%M%S")
|
|
||||||
|
|
||||||
build:
|
|
||||||
docker pull alpine
|
|
||||||
cd $(GOPATH)/src/zero && docker build -t registry.cn-hangzhou.aliyuncs.com/xapp/graceful:$(version) . -f example/graceful/dns/api/Dockerfile
|
|
||||||
|
|
||||||
push: build
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/xapp/graceful:$(version)
|
|
||||||
|
|
||||||
deploy: push
|
|
||||||
kubectl -n kevin set image deployment/graceful-deployment graceful=registry-vpc.cn-hangzhou.aliyuncs.com/xapp/graceful:$(version)
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: graceful
|
|
||||||
namespace: kevin
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
app: graceful
|
|
||||||
type: ClusterIP
|
|
||||||
ports:
|
|
||||||
- name: graceful-port
|
|
||||||
port: 3333
|
|
||||||
targetPort: 8888
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: graceful-deployment
|
|
||||||
namespace: kevin
|
|
||||||
labels:
|
|
||||||
app: graceful
|
|
||||||
spec:
|
|
||||||
replicas: 3
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: graceful
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: graceful
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: graceful
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/graceful:v191022133857
|
|
||||||
imagePullPolicy: Always
|
|
||||||
ports:
|
|
||||||
- containerPort: 8888
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
version := v$(shell /bin/date "+%y%m%d%H%M%S")
|
|
||||||
|
|
||||||
build:
|
|
||||||
docker pull alpine
|
|
||||||
cd $(GOPATH)/src/zero && docker build -t registry.cn-hangzhou.aliyuncs.com/xapp/gracefulrpc:$(version) . -f example/graceful/dns/rpc/Dockerfile
|
|
||||||
|
|
||||||
push: build
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/xapp/gracefulrpc:$(version)
|
|
||||||
|
|
||||||
deploy: push
|
|
||||||
kubectl -n kevin set image deployment/gracefulrpc-deployment gracefulrpc=registry-vpc.cn-hangzhou.aliyuncs.com/xapp/gracefulrpc:$(version)
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: gracefulrpc
|
|
||||||
namespace: kevin
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
app: gracefulrpc
|
|
||||||
type: ClusterIP
|
|
||||||
clusterIP: None
|
|
||||||
ports:
|
|
||||||
- name: gracefulrpc-port
|
|
||||||
port: 3456
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: gracefulrpc-deployment
|
|
||||||
namespace: kevin
|
|
||||||
labels:
|
|
||||||
app: gracefulrpc
|
|
||||||
spec:
|
|
||||||
replicas: 3
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: gracefulrpc
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: gracefulrpc
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: gracefulrpc
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/gracefulrpc:v191022143425
|
|
||||||
imagePullPolicy: Always
|
|
||||||
ports:
|
|
||||||
- containerPort: 3456
|
|
||||||
env:
|
|
||||||
- name: POD_IP
|
|
||||||
valueFrom:
|
|
||||||
fieldRef:
|
|
||||||
fieldPath: status.podIP
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
version := v$(shell /bin/date "+%y%m%d%H%M%S")
|
|
||||||
|
|
||||||
build:
|
|
||||||
docker pull alpine
|
|
||||||
docker pull golang:alpine
|
|
||||||
cd $(GOPATH)/src/zero && docker build -t registry.cn-hangzhou.aliyuncs.com/xapp/graceful:$(version) . -f example/graceful/etcd/api/Dockerfile
|
|
||||||
docker image prune --filter label=stage=gobuilder -f
|
|
||||||
|
|
||||||
push: build
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/xapp/graceful:$(version)
|
|
||||||
|
|
||||||
deploy: push
|
|
||||||
kubectl -n kevin set image deployment/graceful-deployment graceful=registry-vpc.cn-hangzhou.aliyuncs.com/xapp/graceful:$(version)
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: graceful
|
|
||||||
namespace: kevin
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
app: graceful
|
|
||||||
type: ClusterIP
|
|
||||||
ports:
|
|
||||||
- name: graceful-port
|
|
||||||
port: 3333
|
|
||||||
targetPort: 8888
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: graceful-deployment
|
|
||||||
namespace: kevin
|
|
||||||
labels:
|
|
||||||
app: graceful
|
|
||||||
spec:
|
|
||||||
replicas: 3
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: graceful
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: graceful
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: graceful
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/graceful:v191031145905
|
|
||||||
imagePullPolicy: Always
|
|
||||||
ports:
|
|
||||||
- containerPort: 8888
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
version := v$(shell /bin/date "+%y%m%d%H%M%S")
|
|
||||||
|
|
||||||
build:
|
|
||||||
docker pull alpine
|
|
||||||
docker pull golang:alpine
|
|
||||||
cd $(GOPATH)/src/zero && docker build -t registry.cn-hangzhou.aliyuncs.com/xapp/gracefulrpc:$(version) . -f example/graceful/etcd/rpc/Dockerfile
|
|
||||||
docker image prune --filter label=stage=gobuilder -f
|
|
||||||
|
|
||||||
push: build
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/xapp/gracefulrpc:$(version)
|
|
||||||
|
|
||||||
deploy: push
|
|
||||||
kubectl -n kevin set image deployment/gracefulrpc-deployment gracefulrpc=registry-vpc.cn-hangzhou.aliyuncs.com/xapp/gracefulrpc:$(version)
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: gracefulrpc-deployment
|
|
||||||
namespace: kevin
|
|
||||||
labels:
|
|
||||||
app: gracefulrpc
|
|
||||||
spec:
|
|
||||||
replicas: 9
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: gracefulrpc
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: gracefulrpc
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: gracefulrpc
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/gracefulrpc:v191031144304
|
|
||||||
imagePullPolicy: Always
|
|
||||||
ports:
|
|
||||||
- containerPort: 3456
|
|
||||||
env:
|
|
||||||
- name: POD_IP
|
|
||||||
valueFrom:
|
|
||||||
fieldRef:
|
|
||||||
fieldPath: status.podIP
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: gracefulrpc
|
|
||||||
namespace: kevin
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
app: gracefulrpc
|
|
||||||
type: ClusterIP
|
|
||||||
clusterIP: None
|
|
||||||
ports:
|
|
||||||
- name: gracefulrpc-port
|
|
||||||
port: 3456
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: gracefulrpc-deployment
|
|
||||||
namespace: kevin
|
|
||||||
labels:
|
|
||||||
app: gracefulrpc
|
|
||||||
spec:
|
|
||||||
replicas: 9
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: gracefulrpc
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: gracefulrpc
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: gracefulrpc
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/gracefulrpc:v191031144304
|
|
||||||
imagePullPolicy: Always
|
|
||||||
ports:
|
|
||||||
- containerPort: 3456
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: gracefulrpc-deployment
|
|
||||||
namespace: kevin
|
|
||||||
labels:
|
|
||||||
app: gracefulrpc
|
|
||||||
spec:
|
|
||||||
replicas: 9
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: gracefulrpc
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: gracefulrpc
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: gracefulrpc
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/gracefulrpc:v191031144304
|
|
||||||
imagePullPolicy: Always
|
|
||||||
ports:
|
|
||||||
- containerPort: 3456
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
version := v1
|
|
||||||
|
|
||||||
build:
|
|
||||||
cd $(GOPATH)/src/zero && docker build -t registry.cn-hangzhou.aliyuncs.com/xapp/shedding:$(version) . -f example/load/simulate/cpu/Dockerfile
|
|
||||||
|
|
||||||
push: build
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/xapp/shedding:$(version)
|
|
||||||
|
|
||||||
deploy: push
|
|
||||||
kubectl apply -f shedding.yaml
|
|
||||||
|
|
||||||
clean:
|
|
||||||
kubectl delete -f shedding.yaml
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: shedding
|
|
||||||
namespace: adhoc
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: shedding
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/shedding:v1
|
|
||||||
imagePullPolicy: Always
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 1000m
|
|
||||||
limits:
|
|
||||||
cpu: 1000m
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
version := v$(shell /bin/date "+%y%m%d%H%M%S")
|
|
||||||
|
|
||||||
build:
|
|
||||||
cd $(GOPATH)/src/zero && docker build -t registry.cn-hangzhou.aliyuncs.com/xapp/unarydirect:$(version) . -f example/rpc/client/direct/Dockerfile
|
|
||||||
|
|
||||||
push: build
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/xapp/unarydirect:$(version)
|
|
||||||
|
|
||||||
deploy: push
|
|
||||||
kubectl -n adhoc set image deployment/unarydirect-deployment unarydirect=registry-vpc.cn-hangzhou.aliyuncs.com/xapp/unarydirect:$(version)
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: unarydirect-deployment
|
|
||||||
namespace: adhoc
|
|
||||||
labels:
|
|
||||||
app: unarydirect
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: unarydirect
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: unarydirect
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: unarydirect
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/unarydirect:v1
|
|
||||||
imagePullPolicy: Always
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: unaryproxy
|
|
||||||
namespace: kevin
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
app: unaryproxy
|
|
||||||
ports:
|
|
||||||
- name: unaryproxy-port
|
|
||||||
port: 3456
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: unaryproxy-deployment
|
|
||||||
namespace: kevin
|
|
||||||
labels:
|
|
||||||
app: unaryproxy
|
|
||||||
spec:
|
|
||||||
replicas: 3
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: unaryproxy
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: unaryproxy
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: unaryproxy
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/unaryproxy:v1
|
|
||||||
imagePullPolicy: Always
|
|
||||||
ports:
|
|
||||||
- containerPort: 3456
|
|
||||||
volumeMounts:
|
|
||||||
- name: timezone
|
|
||||||
mountPath: /etc/localtime
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
volumes:
|
|
||||||
- name: timezone
|
|
||||||
hostPath:
|
|
||||||
path: /usr/share/zoneinfo/Asia/Shanghai
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
version := v1
|
|
||||||
|
|
||||||
build:
|
|
||||||
cd $(GOPATH)/src/zero && docker build -t registry.cn-hangzhou.aliyuncs.com/xapp/unaryserver:$(version) . -f example/rpc/server/unary/Dockerfile
|
|
||||||
docker image prune --filter label=stage=gobuilder -f
|
|
||||||
|
|
||||||
push: build
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/xapp/unaryserver:$(version)
|
|
||||||
|
|
||||||
deploy: push
|
|
||||||
kubectl -n adhoc set image deployment/unaryserver-deployment unaryserver=registry-vpc.cn-hangzhou.aliyuncs.com/xapp/unaryserver:$(version)
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: unaryserver-deployment
|
|
||||||
namespace: adhoc
|
|
||||||
labels:
|
|
||||||
app: unaryserver
|
|
||||||
spec:
|
|
||||||
replicas: 3
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: unaryserver
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: unaryserver
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: unaryserver
|
|
||||||
image: registry-vpc.cn-hangzhou.aliyuncs.com/xapp/unaryserver:v1
|
|
||||||
imagePullPolicy: Always
|
|
||||||
ports:
|
|
||||||
- containerPort: 3456
|
|
||||||
imagePullSecrets:
|
|
||||||
- name: aliyun
|
|
||||||
30
readme.md
30
readme.md
@@ -89,15 +89,17 @@ go get -u github.com/tal-tech/go-zero
|
|||||||
|
|
||||||
## 6. Quick Start
|
## 6. Quick Start
|
||||||
|
|
||||||
0. 完整示例请查看[从0到1快速构建一个高并发的微服务系统](doc/shorturl.md)
|
0. 完整示例请查看
|
||||||
|
|
||||||
1. 编译goctl工具
|
[快速构建高并发微服务](doc/shorturl.md)
|
||||||
|
|
||||||
|
1. 安装goctl工具
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
go build tools/goctl/goctl.go
|
export GO111MODULE=on export GOPROXY=https://goproxy.cn/,direct go get github.com/tal-tech/go-zero/tools/goctl
|
||||||
```
|
```
|
||||||
|
|
||||||
把goctl放到$PATH的目录下,确保goctl可执行
|
确保goctl可执行
|
||||||
|
|
||||||
2. 定义API文件,比如greet.api,可以在vs code里安装`goctl`插件,支持api语法
|
2. 定义API文件,比如greet.api,可以在vs code里安装`goctl`插件,支持api语法
|
||||||
|
|
||||||
@@ -135,7 +137,7 @@ go get -u github.com/tal-tech/go-zero
|
|||||||
```
|
```
|
||||||
├── greet
|
├── greet
|
||||||
│ ├── etc
|
│ ├── etc
|
||||||
│ │ └── greet-api.json // 配置文件
|
│ │ └── greet-api.yaml // 配置文件
|
||||||
│ ├── greet.go // main文件
|
│ ├── greet.go // main文件
|
||||||
│ └── internal
|
│ └── internal
|
||||||
│ ├── config
|
│ ├── config
|
||||||
@@ -152,18 +154,24 @@ go get -u github.com/tal-tech/go-zero
|
|||||||
└── greet.api // api描述文件
|
└── greet.api // api描述文件
|
||||||
```
|
```
|
||||||
生成的代码可以直接运行:
|
生成的代码可以直接运行:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
cd greet
|
cd greet
|
||||||
go run greet.go -f etc/greet-api.json
|
go run greet.go -f etc/greet-api.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
默认侦听在8888端口(可以在配置文件里修改),可以通过curl请求:
|
默认侦听在8888端口(可以在配置文件里修改),可以通过curl请求:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
➜ go-zero git:(master) curl -w "\ncode: %{http_code}\n" http://localhost:8888/greet/from/kevin
|
curl -i http://localhost:8888/greet/from/you
|
||||||
{"code":0}
|
```
|
||||||
code: 200
|
|
||||||
|
返回如下:
|
||||||
|
|
||||||
|
```http
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Date: Sun, 30 Aug 2020 15:32:35 GMT
|
||||||
|
Content-Length: 0
|
||||||
```
|
```
|
||||||
|
|
||||||
编写业务代码:
|
编写业务代码:
|
||||||
@@ -187,7 +195,7 @@ go get -u github.com/tal-tech/go-zero
|
|||||||
|
|
||||||
## 8. 文档 (逐步完善中)
|
## 8. 文档 (逐步完善中)
|
||||||
|
|
||||||
* [从0到1快速构建一个高并发的微服务系统](doc/shorturl.md)
|
* [快速构建高并发微服务](doc/shorturl.md)
|
||||||
* [goctl使用帮助](doc/goctl.md)
|
* [goctl使用帮助](doc/goctl.md)
|
||||||
* [关键字替换和敏感词过滤工具](doc/keywords.md)
|
* [关键字替换和敏感词过滤工具](doc/keywords.md)
|
||||||
|
|
||||||
|
|||||||
@@ -2,3 +2,9 @@ version := $(shell /bin/date "+%Y-%m-%d %H:%M")
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" goctl.go && upx goctl
|
go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" goctl.go && upx goctl
|
||||||
|
mac:
|
||||||
|
GOOS=darwin go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" -o goctl-darwin goctl.go && upx goctl-darwin
|
||||||
|
win:
|
||||||
|
GOOS=windows go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" -o goctl.exe goctl.go && upx goctl.exe
|
||||||
|
linux:
|
||||||
|
GOOS=linux go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" -o goctl-linux goctl.go && upx goctl-linux
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ func ApiFormat(path string, printToConsole bool) error {
|
|||||||
_, err := fmt.Print(result)
|
_, err := fmt.Print(result)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
result = strings.TrimSpace(result)
|
||||||
return ioutil.WriteFile(path, []byte(result), os.ModePerm)
|
return ioutil.WriteFile(path, []byte(result), os.ModePerm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,23 +141,26 @@ func createGoModFileIfNeed(dir string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, hasGoMod := util.FindGoModPath(dir)
|
_, hasGoMod := util.FindGoModPath(dir)
|
||||||
if !hasGoMod {
|
if hasGoMod {
|
||||||
gopath := os.Getenv("GOPATH")
|
return
|
||||||
parent := path.Join(gopath, "src")
|
|
||||||
pos := strings.Index(absDir, parent)
|
|
||||||
if pos < 0 {
|
|
||||||
moduleName := absDir[len(filepath.Dir(absDir))+1:]
|
|
||||||
cmd := exec.Command("go", "mod", "init", moduleName)
|
|
||||||
cmd.Dir = dir
|
|
||||||
var stdout, stderr bytes.Buffer
|
|
||||||
cmd.Stdout = &stdout
|
|
||||||
cmd.Stderr = &stderr
|
|
||||||
err := cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
}
|
|
||||||
outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes())
|
|
||||||
fmt.Printf(outStr + "\n" + errStr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gopath := os.Getenv("GOPATH")
|
||||||
|
parent := path.Join(gopath, "src")
|
||||||
|
pos := strings.Index(absDir, parent)
|
||||||
|
if pos >= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
moduleName := absDir[len(filepath.Dir(absDir))+1:]
|
||||||
|
cmd := exec.Command("go", "mod", "init", moduleName)
|
||||||
|
cmd.Dir = dir
|
||||||
|
var stdout, stderr bytes.Buffer
|
||||||
|
cmd.Stdout = &stdout
|
||||||
|
cmd.Stderr = &stderr
|
||||||
|
if err = cmd.Run(); err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
}
|
||||||
|
outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes())
|
||||||
|
fmt.Printf(outStr + "\n" + errStr)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,18 +20,22 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type {{.logic}} struct {
|
type {{.logic}} struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
logx.Logger
|
logx.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func New{{.logic}}(ctx context.Context, svcCtx *svc.ServiceContext) {{.logic}} {
|
func New{{.logic}}(ctx context.Context, svcCtx *svc.ServiceContext) {{.logic}} {
|
||||||
return {{.logic}}{
|
return {{.logic}}{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
Logger: logx.WithContext(ctx),
|
Logger: logx.WithContext(ctx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *{{.logic}}) {{.function}}({{.request}}) {{.responseType}} {
|
func (l *{{.logic}}) {{.function}}({{.request}}) {{.responseType}} {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
{{.returnString}}
|
{{.returnString}}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ func getParentPackage(dir string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
absDir = strings.ReplaceAll(absDir, `\`, `/`)
|
absDir = strings.ReplaceAll(absDir, `\`, `/`)
|
||||||
var rootPath, hasGoMod = goctlutil.FindGoModPath(dir)
|
rootPath, hasGoMod := goctlutil.FindGoModPath(dir)
|
||||||
if hasGoMod {
|
if hasGoMod {
|
||||||
return rootPath, nil
|
return rootPath, nil
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,7 @@ func getParentPackage(dir string) (string, error) {
|
|||||||
pos := strings.Index(absDir, parent)
|
pos := strings.Index(absDir, parent)
|
||||||
if pos < 0 {
|
if pos < 0 {
|
||||||
fmt.Printf("%s not in go.mod project path, or not in GOPATH of %s directory\n", absDir, gopath)
|
fmt.Printf("%s not in go.mod project path, or not in GOPATH of %s directory\n", absDir, gopath)
|
||||||
var tempPath = filepath.Dir(absDir)
|
tempPath := filepath.Dir(absDir)
|
||||||
rootPath = absDir[len(tempPath)+1:]
|
rootPath = absDir[len(tempPath)+1:]
|
||||||
} else {
|
} else {
|
||||||
rootPath = absDir[len(parent)+1:]
|
rootPath = absDir[len(parent)+1:]
|
||||||
@@ -61,7 +61,7 @@ func writeProperty(writer io.Writer, name, tp, tag, comment string, indent int)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getAuths(api *spec.ApiSpec) []string {
|
func getAuths(api *spec.ApiSpec) []string {
|
||||||
var authNames = collection.NewSet()
|
authNames := collection.NewSet()
|
||||||
for _, g := range api.Service.Groups {
|
for _, g := range api.Service.Groups {
|
||||||
if value, ok := util.GetAnnotationValue(g.Annotations, "server", "jwt"); ok {
|
if value, ok := util.GetAnnotationValue(g.Annotations, "server", "jwt"); ok {
|
||||||
authNames.Add(value)
|
authNames.Add(value)
|
||||||
@@ -78,5 +78,6 @@ func formatCode(code string) string {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(ret)
|
return string(ret)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,14 +9,9 @@ import (
|
|||||||
|
|
||||||
func DockerCommand(c *cli.Context) error {
|
func DockerCommand(c *cli.Context) error {
|
||||||
goFile := c.String("go")
|
goFile := c.String("go")
|
||||||
namespace := c.String("namespace")
|
if len(goFile) == 0 {
|
||||||
if len(goFile) == 0 || len(namespace) == 0 {
|
return errors.New("-go can't be empty")
|
||||||
return errors.New("-go and -namespace can't be empty")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := gen.GenerateDockerfile(goFile, "-f", "etc/config.json"); err != nil {
|
return gen.GenerateDockerfile(goFile, "-f", "etc/config.yaml")
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return gen.GenerateMakefile(goFile, namespace)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package gen
|
package gen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
@@ -9,11 +10,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func GenerateDockerfile(goFile string, args ...string) error {
|
func GenerateDockerfile(goFile string, args ...string) error {
|
||||||
relPath, err := util.PathFromGoSrc()
|
projPath, err := getFilePath(filepath.Dir(goFile))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pos := strings.IndexByte(projPath, '/')
|
||||||
|
if pos >= 0 {
|
||||||
|
projPath = projPath[pos+1:]
|
||||||
|
}
|
||||||
|
|
||||||
out, err := util.CreateIfNotExist("Dockerfile")
|
out, err := util.CreateIfNotExist("Dockerfile")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -28,7 +34,7 @@ func GenerateDockerfile(goFile string, args ...string) error {
|
|||||||
t := template.Must(template.New("dockerfile").Parse(dockerTemplate))
|
t := template.Must(template.New("dockerfile").Parse(dockerTemplate))
|
||||||
return t.Execute(out, map[string]string{
|
return t.Execute(out, map[string]string{
|
||||||
"projectName": vars.ProjectName,
|
"projectName": vars.ProjectName,
|
||||||
"goRelPath": relPath,
|
"goRelPath": projPath,
|
||||||
"goFile": goFile,
|
"goFile": goFile,
|
||||||
"exeFile": util.FileNameWithoutExt(goFile),
|
"exeFile": util.FileNameWithoutExt(goFile),
|
||||||
"argument": builder.String(),
|
"argument": builder.String(),
|
||||||
|
|||||||
26
tools/goctl/gen/filepath.go
Normal file
26
tools/goctl/gen/filepath.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package gen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getFilePath(file string) (string, error) {
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
projPath, ok := util.FindGoModPath(filepath.Join(wd, file))
|
||||||
|
if !ok {
|
||||||
|
projPath, err = util.PathFromGoSrc()
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.New("no go.mod found, or not in GOPATH")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return projPath, nil
|
||||||
|
}
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
package gen
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GenerateMakefile(goFile, namespace string) error {
|
|
||||||
relPath, err := util.PathFromGoSrc()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
movePath, err := getMovePath()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := util.CreateIfNotExist("Makefile")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer out.Close()
|
|
||||||
|
|
||||||
t := template.Must(template.New("makefile").Parse(makefileTemplate))
|
|
||||||
return t.Execute(out, map[string]string{
|
|
||||||
"rootRelPath": movePath,
|
|
||||||
"relPath": relPath,
|
|
||||||
"exeFile": util.FileNameWithoutExt(goFile),
|
|
||||||
"namespace": namespace,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func getMovePath() (string, error) {
|
|
||||||
relPath, err := util.PathFromGoSrc()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
var builder strings.Builder
|
|
||||||
for range strings.Split(relPath, "/") {
|
|
||||||
builder.WriteString("../")
|
|
||||||
}
|
|
||||||
|
|
||||||
if move := builder.String(); len(move) == 0 {
|
|
||||||
return ".", nil
|
|
||||||
} else {
|
|
||||||
return move, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package gen
|
package gen
|
||||||
|
|
||||||
const (
|
const dockerTemplate = `FROM golang:alpine AS builder
|
||||||
dockerTemplate = `FROM golang:alpine AS builder
|
|
||||||
|
|
||||||
LABEL stage=gobuilder
|
LABEL stage=gobuilder
|
||||||
|
|
||||||
@@ -26,19 +25,3 @@ COPY --from=builder /app/{{.exeFile}} /app/{{.exeFile}}
|
|||||||
|
|
||||||
CMD ["./{{.exeFile}}"{{.argument}}]
|
CMD ["./{{.exeFile}}"{{.argument}}]
|
||||||
`
|
`
|
||||||
|
|
||||||
makefileTemplate = `version := v$(shell /bin/date "+%y%m%d%H%M%S")
|
|
||||||
|
|
||||||
build:
|
|
||||||
docker pull alpine
|
|
||||||
docker pull golang:alpine
|
|
||||||
cd $(GOPATH)/src/xiao && docker build -t registry.cn-hangzhou.aliyuncs.com/xapp/{{.exeFile}}:$(version) . -f {{.relPath}}/Dockerfile
|
|
||||||
docker image prune --filter label=stage=gobuilder -f
|
|
||||||
|
|
||||||
push: build
|
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/xapp/{{.exeFile}}:$(version)
|
|
||||||
|
|
||||||
deploy: push
|
|
||||||
kubectl -n {{.namespace}} set image deployment/{{.exeFile}}-deployment {{.exeFile}}=registry-vpc.cn-hangzhou.aliyuncs.com/xapp/{{.exeFile}}:$(version)
|
|
||||||
`
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ func MustCreateRpcContext(protoSrc, targetDir, serviceName string, idea bool) *R
|
|||||||
func MustCreateRpcContextFromCli(ctx *cli.Context) *RpcContext {
|
func MustCreateRpcContextFromCli(ctx *cli.Context) *RpcContext {
|
||||||
os := runtime.GOOS
|
os := runtime.GOOS
|
||||||
switch os {
|
switch os {
|
||||||
case "darwin", "windows":
|
case "darwin", "linux", "windows":
|
||||||
default:
|
default:
|
||||||
logx.Must(fmt.Errorf("unexpected os: %s", os))
|
logx.Must(fmt.Errorf("unexpected os: %s", os))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,13 +12,14 @@ func Run(arg string) (string, error) {
|
|||||||
goos := runtime.GOOS
|
goos := runtime.GOOS
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
switch goos {
|
switch goos {
|
||||||
case "darwin":
|
case "darwin", "linux":
|
||||||
cmd = exec.Command("sh", "-c", arg)
|
cmd = exec.Command("sh", "-c", arg)
|
||||||
case "windows":
|
case "windows":
|
||||||
cmd = exec.Command("cmd.exe", "/c", arg)
|
cmd = exec.Command("cmd.exe", "/c", arg)
|
||||||
default:
|
default:
|
||||||
return "", fmt.Errorf("unexpected os: %v", goos)
|
return "", fmt.Errorf("unexpected os: %v", goos)
|
||||||
}
|
}
|
||||||
|
|
||||||
dtsout := new(bytes.Buffer)
|
dtsout := new(bytes.Buffer)
|
||||||
stderr := new(bytes.Buffer)
|
stderr := new(bytes.Buffer)
|
||||||
cmd.Stdout = dtsout
|
cmd.Stdout = dtsout
|
||||||
@@ -30,5 +31,6 @@ func Run(arg string) (string, error) {
|
|||||||
}
|
}
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return dtsout.String(), nil
|
return dtsout.String(), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func (g *defaultRpcGenerator) mustGetPackage(dir string) string {
|
|||||||
switch os {
|
switch os {
|
||||||
case "windows":
|
case "windows":
|
||||||
relativePath = filepath.ToSlash(relativePath)
|
relativePath = filepath.ToSlash(relativePath)
|
||||||
case "darwin":
|
case "darwin", "linux":
|
||||||
default:
|
default:
|
||||||
g.Ctx.Fatalln("unexpected os: %s", os)
|
g.Ctx.Fatalln("unexpected os: %s", os)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const etcTemplate = `Name: {{.serviceName}}.rpc
|
const etcTemplate = `Name: {{.serviceName}}.rpc
|
||||||
Log:
|
|
||||||
Mode: console
|
|
||||||
ListenOn: 127.0.0.1:8080
|
ListenOn: 127.0.0.1:8080
|
||||||
Etcd:
|
Etcd:
|
||||||
Hosts:
|
Hosts:
|
||||||
|
|||||||
@@ -22,13 +22,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type {{.logicName}} struct {
|
type {{.logicName}} struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
logx.Logger
|
logx.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func New{{.logicName}}(ctx context.Context,svcCtx *svc.ServiceContext) *{{.logicName}} {
|
func New{{.logicName}}(ctx context.Context,svcCtx *svc.ServiceContext) *{{.logicName}} {
|
||||||
return &{{.logicName}}{
|
return &{{.logicName}}{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
Logger: logx.WithContext(ctx),
|
Logger: logx.WithContext(ctx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user