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网址,通过程序计算等方式,转换为简短的网址字符串。
|
||||
|
||||
写此短链服务是为了从整体上演示go-zero构建完整微服务的过程,算法和实现细节尽可能简化了,所以这不是一个高阶的短链服务。
|
||||
|
||||
## 1. 短链微服务架构图
|
||||
## 2. 短链微服务架构图
|
||||
|
||||
<img src="images/shorturl-arch.png" alt="架构图" width="800" />
|
||||
|
||||
## 2. 准备工作
|
||||
* 这里只用了`Transform RPC`一个微服务,并不是说API Gateway只能调用一个微服务,只是为了最简演示API Gateway如何调用RPC微服务而已
|
||||
* 在真正项目里要尽可能每个微服务使用自己的数据库,数据边界要清晰
|
||||
|
||||
## 3. 准备工作
|
||||
|
||||
* 安装etcd, mysql, redis
|
||||
* 准备goctl工具
|
||||
* 直接从`https://github.com/tal-tech/go-zero/releases`下载最新版,后续会加上自动更新
|
||||
* 也可以从源码编译,在任意目录下进行,目的是为了编译goctl工具
|
||||
|
||||
1. `git clone https://github.com/tal-tech/go-zero`
|
||||
2. 在`tools/goctl`目录下编译goctl工具`go build goctl.go`
|
||||
3. 将生成的goctl放到`$PATH`下,确保goctl命令可运行
|
||||
|
||||
* 安装goctl工具
|
||||
|
||||
```shell
|
||||
export GO111MODULE=on export GOPROXY=https://goproxy.cn/,direct go get github.com/tal-tech/go-zero/tools/goctl
|
||||
```
|
||||
|
||||
* 创建工作目录`shorturl`
|
||||
|
||||
* 在`shorturl`目录下执行`go mod init shorturl`初始化`go.mod`
|
||||
|
||||
## 3. 编写API Gateway代码
|
||||
## 4. 编写API Gateway代码
|
||||
|
||||
* 通过goctl生成`shorturl.api`并编辑,为了简洁,去除了文件开头的`info`,代码如下:
|
||||
* 通过goctl生成`api/shorturl.api`并编辑,为了简洁,去除了文件开头的`info`,代码如下:
|
||||
|
||||
```go
|
||||
type (
|
||||
expandReq struct {
|
||||
shorten string `form:"shorten"`
|
||||
}
|
||||
|
||||
expandResp struct {
|
||||
url string `json:"url"`
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
shortenReq struct {
|
||||
url string `form:"url"`
|
||||
}
|
||||
|
||||
shortenResp struct {
|
||||
shortUrl string `json:"shortUrl"`
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
expandReq struct {
|
||||
key string `form:"key"`
|
||||
}
|
||||
|
||||
expandResp struct {
|
||||
url string `json:"url"`
|
||||
shorten string `json:"shorten"`
|
||||
}
|
||||
)
|
||||
|
||||
@@ -71,7 +98,7 @@
|
||||
* 使用goctl生成API Gateway代码
|
||||
|
||||
```shell
|
||||
goctl api go -api shorturl.api -dir api
|
||||
goctl api go -api shorturl.api -dir .
|
||||
```
|
||||
|
||||
生成的文件结构如下:
|
||||
@@ -95,16 +122,16 @@
|
||||
│ │ │ └── servicecontext.go // 定义ServiceContext
|
||||
│ │ └── types
|
||||
│ │ └── types.go // 定义请求、返回结构体
|
||||
│ ├── shorturl.api
|
||||
│ └── shorturl.go // main入口定义
|
||||
├── go.mod
|
||||
├── go.sum
|
||||
└── shorturl.api
|
||||
└── go.sum
|
||||
```
|
||||
|
||||
* 启动API Gateway服务,默认侦听在8888端口
|
||||
|
||||
```shell
|
||||
go run api/shorturl.go -f api/etc/shorturl-api.yaml
|
||||
go run shorturl.go -f etc/shorturl-api.yaml
|
||||
```
|
||||
|
||||
* 测试API Gateway服务
|
||||
@@ -134,14 +161,14 @@
|
||||
|
||||
* 到这里,你已经可以通过goctl生成客户端代码给客户端同学并行开发了,支持多种语言,详见文档
|
||||
|
||||
## 4. 编写shorten rpc服务
|
||||
## 5. 编写transform rpc服务
|
||||
|
||||
* 在`rpc/shorten`目录下编写`shorten.proto`文件
|
||||
* 在`rpc/transform`目录下编写`transform.proto`文件
|
||||
|
||||
可以通过命令生成proto文件模板
|
||||
|
||||
```shell
|
||||
goctl rpc template -o shorten.proto
|
||||
goctl rpc template -o transform.proto
|
||||
```
|
||||
|
||||
修改后文件内容如下:
|
||||
@@ -149,183 +176,120 @@
|
||||
```protobuf
|
||||
syntax = "proto3";
|
||||
|
||||
package shorten;
|
||||
|
||||
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;
|
||||
package transform;
|
||||
|
||||
message expandReq {
|
||||
string key = 1;
|
||||
string shorten = 1;
|
||||
}
|
||||
|
||||
message expandResp {
|
||||
string url = 1;
|
||||
}
|
||||
|
||||
service expander {
|
||||
message shortenReq {
|
||||
string url = 1;
|
||||
}
|
||||
|
||||
message shortenResp {
|
||||
string shorten = 1;
|
||||
}
|
||||
|
||||
service transformer {
|
||||
rpc expand(expandReq) returns(expandResp);
|
||||
rpc shorten(shortenReq) returns(shortenResp);
|
||||
}
|
||||
```
|
||||
|
||||
* 用`goctl`生成rpc代码,在`rpc/expand`目录下执行命令
|
||||
* 用`goctl`生成rpc代码,在`rpc/transform`目录下执行命令
|
||||
|
||||
```shell
|
||||
goctl rpc proto -src expand.proto
|
||||
goctl rpc proto -src transform.proto
|
||||
```
|
||||
|
||||
文件结构如下:
|
||||
|
||||
```
|
||||
rpc/expand
|
||||
rpc/transform
|
||||
├── etc
|
||||
│ └── expand.yaml // 配置文件
|
||||
├── expand.go // rpc服务main函数
|
||||
├── expand.proto
|
||||
├── expander
|
||||
│ ├── expander.go // 提供了外部调用方法,无需修改
|
||||
│ ├── expander_mock.go // mock方法,测试用
|
||||
│ └── types.go // request/response结构体定义
|
||||
│ └── transform.yaml // 配置文件
|
||||
├── internal
|
||||
│ ├── config
|
||||
│ │ └── config.go // 配置定义
|
||||
│ │ └── config.go // 配置定义
|
||||
│ ├── logic
|
||||
│ │ └── expandlogic.go // rpc业务逻辑在这里实现
|
||||
│ │ ├── expandlogic.go // expand业务逻辑在这里实现
|
||||
│ │ └── shortenlogic.go // shorten业务逻辑在这里实现
|
||||
│ ├── server
|
||||
│ │ └── expanderserver.go // 调用入口, 不需要修改
|
||||
│ │ └── transformerserver.go // 调用入口, 不需要修改
|
||||
│ └── svc
|
||||
│ └── servicecontext.go // 定义ServiceContext,传递依赖
|
||||
└── pb
|
||||
└── expand.pb.go
|
||||
│ └── servicecontext.go // 定义ServiceContext,传递依赖
|
||||
├── pb
|
||||
│ └── 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
|
||||
$ go run expand.go -f etc/expand.yaml
|
||||
Starting rpc server at 127.0.0.1:8081...
|
||||
$ go run transform.go -f etc/transform.yaml
|
||||
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
|
||||
Shortener:
|
||||
Transform:
|
||||
Etcd:
|
||||
Hosts:
|
||||
- localhost:2379
|
||||
Key: shorten.rpc
|
||||
Expander:
|
||||
Etcd:
|
||||
Hosts:
|
||||
- localhost:2379
|
||||
Key: expand.rpc
|
||||
Key: transform.rpc
|
||||
```
|
||||
|
||||
通过etcd自动去发现可用的shorten/expand服务
|
||||
通过etcd自动去发现可用的transform服务
|
||||
|
||||
* 修改`internal/config/config.go`如下,增加shorten/expand服务依赖
|
||||
* 修改`internal/config/config.go`如下,增加transform服务依赖
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
rest.RestConf
|
||||
Shortener rpcx.RpcClientConf // 手动代码
|
||||
Expander rpcx.RpcClientConf // 手动代码
|
||||
Transform rpcx.RpcClientConf // 手动代码
|
||||
}
|
||||
```
|
||||
|
||||
* 修改`internal/logic/expandlogic.go`,如下:
|
||||
* 修改`internal/svc/servicecontext.go`,如下:
|
||||
|
||||
```go
|
||||
type ExpandLogic struct {
|
||||
ctx context.Context
|
||||
logx.Logger
|
||||
expander rpcx.Client // 手动代码
|
||||
type ServiceContext struct {
|
||||
Config config.Config
|
||||
Transformer rpcx.Client // 手动代码
|
||||
}
|
||||
|
||||
func NewExpandLogic(ctx context.Context, svcCtx *svc.ServiceContext) ExpandLogic {
|
||||
return ExpandLogic{
|
||||
ctx: ctx,
|
||||
Logger: logx.WithContext(ctx),
|
||||
expander: svcCtx.Expander, // 手动代码
|
||||
func NewServiceContext(c config.Config) *ServiceContext {
|
||||
return &ServiceContext{
|
||||
Config: c,
|
||||
Transformer: rpcx.MustNewClient(c.Transform), // 手动代码
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
通过ServiceContext在不同业务逻辑之间传递依赖
|
||||
|
||||
* 修改`internal/logic/expandlogic.go`里的`Expand`方法,如下:
|
||||
|
||||
```go
|
||||
func (l *ExpandLogic) Expand(req types.ExpandReq) (*types.ExpandResp, error) {
|
||||
// 手动代码开始
|
||||
resp, err := expander.NewExpander(l.expander).Expand(l.ctx, &expander.ExpandReq{
|
||||
Key: req.Key,
|
||||
trans := transformer.NewTransformer(l.svcCtx.Transformer)
|
||||
resp, err := trans.Expand(l.ctx, &transformer.ExpandReq{
|
||||
Shorten: req.Shorten,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -338,28 +302,15 @@
|
||||
}
|
||||
```
|
||||
|
||||
增加了对`expander`服务的依赖,并通过调用`expander`的`Expand`方法实现短链恢复到url
|
||||
通过调用`transformer`的`Expand`方法实现短链恢复到url
|
||||
|
||||
* 修改`internal/logic/shortenlogic.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) {
|
||||
// 手动代码开始
|
||||
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,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -367,49 +318,28 @@
|
||||
}
|
||||
|
||||
return &types.ShortenResp{
|
||||
ShortUrl: resp.Key,
|
||||
Shorten: resp.Shorten,
|
||||
}, nil
|
||||
// 手动代码结束
|
||||
}
|
||||
```
|
||||
|
||||
增加了对`shortener`服务的依赖,并通过调用`shortener`的`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在不同业务逻辑之间传递依赖
|
||||
通过调用`transformer`的`Shorten`方法实现url到短链的变换
|
||||
|
||||
至此,API Gateway修改完成,虽然贴的代码多,但是期中修改的是很少的一部分,为了方便理解上下文,我贴了完整代码,接下来处理CRUD+cache
|
||||
|
||||
## 7. 定义数据库表结构,并生成CRUD+cache代码
|
||||
|
||||
* shorturl下创建rpc/model目录:`mkdir -p rpc/model`
|
||||
* 在roc/model目录下编写创建shorturl表的sql文件`shorturl.sql`,如下:
|
||||
* shorturl下创建`rpc/transform/model`目录:`mkdir -p rpc/transform/model`
|
||||
|
||||
* 在rpc/transform/model目录下编写创建shorturl表的sql文件`shorturl.sql`,如下:
|
||||
|
||||
```sql
|
||||
CREATE TABLE `shorturl`
|
||||
(
|
||||
`id` bigint(10) NOT NULL AUTO_INCREMENT,
|
||||
`key` varchar(255) NOT NULL DEFAULT '' COMMENT 'shorten key',
|
||||
`url` varchar(255) DEFAULT '' COMMENT 'original url',
|
||||
PRIMARY KEY(`id`),
|
||||
UNIQUE KEY `key_index`(`key`)
|
||||
`shorten` varchar(255) NOT NULL COMMENT 'shorten key',
|
||||
`url` varchar(255) NOT NULL COMMENT 'original url',
|
||||
PRIMARY KEY(`shorten`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
```
|
||||
|
||||
@@ -423,18 +353,18 @@
|
||||
source shorturl.sql;
|
||||
```
|
||||
|
||||
* 在`rpc/model`目录下执行如下命令生成CRUD+cache代码,`-c`表示使用`redis cache`
|
||||
* 在`rpc/transform/model`目录下执行如下命令生成CRUD+cache代码,`-c`表示使用`redis cache`
|
||||
|
||||
```shell
|
||||
goctl model mysql ddl -c -src shorturl.sql -dir .
|
||||
```
|
||||
|
||||
|
||||
也可以用`datasource`命令代替`ddl`来指定数据库链接直接从schema生成
|
||||
|
||||
|
||||
生成后的文件结构如下:
|
||||
|
||||
|
||||
```
|
||||
rpc/model
|
||||
rpc/transform/model
|
||||
├── shorturl.sql
|
||||
├── shorturlmodel.go // CRUD+cache代码
|
||||
└── vars.go // 定义常量和变量
|
||||
@@ -442,7 +372,7 @@
|
||||
|
||||
## 8. 修改shorten/expand rpc代码调用crud+cache代码
|
||||
|
||||
* 修改`rpc/expand/etc/expand.yaml`,增加如下内容:
|
||||
* 修改`rpc/transform/etc/transform.yaml`,增加如下内容:
|
||||
|
||||
```yaml
|
||||
DataSource: root:@tcp(localhost:3306)/gozero
|
||||
@@ -453,7 +383,7 @@
|
||||
|
||||
可以使用多个redis作为cache,支持redis单点或者redis集群
|
||||
|
||||
* 修改`rpc/expand/internal/config.go`,如下:
|
||||
* 修改`rpc/transform/internal/config.go`,如下:
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
@@ -466,116 +396,46 @@
|
||||
|
||||
增加了mysql和redis cache配置
|
||||
|
||||
* 修改`rpc/expand/internal/svc/servicecontext.go`,如下:
|
||||
* 修改`rpc/transform/internal/svc/servicecontext.go`,如下:
|
||||
|
||||
```go
|
||||
type ServiceContext struct {
|
||||
c config.Config
|
||||
Model *model.ShorturlModel // 手动代码
|
||||
Model *model.ShorturlModel // 手动代码
|
||||
}
|
||||
|
||||
func NewServiceContext(c config.Config) *ServiceContext {
|
||||
return &ServiceContext{
|
||||
c: c,
|
||||
c: c,
|
||||
Model: model.NewShorturlModel(sqlx.NewMysql(c.DataSource), c.Cache, c.Table), // 手动代码
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* 修改`rpc/expand/internal/logic/expandlogic.go`,如下:
|
||||
* 修改`rpc/transform/internal/logic/expandlogic.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) {
|
||||
// 手动代码开始
|
||||
res, err := l.model.FindOne(in.Key)
|
||||
// 手动代码开始
|
||||
res, err := l.svcCtx.Model.FindOne(in.Shorten)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &expand.ExpandResp{
|
||||
return &transform.ExpandResp{
|
||||
Url: res.Url,
|
||||
}, 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`,如下:
|
||||
|
||||
```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) {
|
||||
// 手动代码开始,生成短链接
|
||||
key := hash.Md5Hex([]byte(in.Url))[:keyLen]
|
||||
_, err := l.model.Insert(model.Shorturl{
|
||||
key := hash.Md5Hex([]byte(in.Url))[:6]
|
||||
_, err := l.svcCtx.Model.Insert(model.Shorturl{
|
||||
Shorten: key,
|
||||
Url: in.Url,
|
||||
})
|
||||
@@ -583,8 +443,8 @@
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &shorten.ShortenResp{
|
||||
Key: key,
|
||||
return &transform.ShortenResp{
|
||||
Shorten: key,
|
||||
}, nil
|
||||
// 手动代码结束
|
||||
}
|
||||
@@ -597,7 +457,7 @@
|
||||
* shorten api调用
|
||||
|
||||
```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
|
||||
Content-Length: 21
|
||||
|
||||
{"shortUrl":"f35b2a"}
|
||||
{"shorten":"f35b2a"}
|
||||
```
|
||||
|
||||
* expand api调用
|
||||
|
||||
```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
|
||||
|
||||
0. 完整示例请查看[从0到1快速构建一个高并发的微服务系统](doc/shorturl.md)
|
||||
0. 完整示例请查看
|
||||
|
||||
1. 编译goctl工具
|
||||
[快速构建高并发微服务](doc/shorturl.md)
|
||||
|
||||
1. 安装goctl工具
|
||||
|
||||
```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语法
|
||||
|
||||
@@ -135,7 +137,7 @@ go get -u github.com/tal-tech/go-zero
|
||||
```
|
||||
├── greet
|
||||
│ ├── etc
|
||||
│ │ └── greet-api.json // 配置文件
|
||||
│ │ └── greet-api.yaml // 配置文件
|
||||
│ ├── greet.go // main文件
|
||||
│ └── internal
|
||||
│ ├── config
|
||||
@@ -152,18 +154,24 @@ go get -u github.com/tal-tech/go-zero
|
||||
└── greet.api // api描述文件
|
||||
```
|
||||
生成的代码可以直接运行:
|
||||
|
||||
|
||||
```shell
|
||||
cd greet
|
||||
go run greet.go -f etc/greet-api.json
|
||||
go run greet.go -f etc/greet-api.yaml
|
||||
```
|
||||
|
||||
默认侦听在8888端口(可以在配置文件里修改),可以通过curl请求:
|
||||
|
||||
```shell
|
||||
➜ go-zero git:(master) curl -w "\ncode: %{http_code}\n" http://localhost:8888/greet/from/kevin
|
||||
{"code":0}
|
||||
code: 200
|
||||
curl -i http://localhost:8888/greet/from/you
|
||||
```
|
||||
|
||||
返回如下:
|
||||
|
||||
```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. 文档 (逐步完善中)
|
||||
|
||||
* [从0到1快速构建一个高并发的微服务系统](doc/shorturl.md)
|
||||
* [快速构建高并发微服务](doc/shorturl.md)
|
||||
* [goctl使用帮助](doc/goctl.md)
|
||||
* [关键字替换和敏感词过滤工具](doc/keywords.md)
|
||||
|
||||
|
||||
@@ -2,3 +2,9 @@ version := $(shell /bin/date "+%Y-%m-%d %H:%M")
|
||||
|
||||
build:
|
||||
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)
|
||||
return err
|
||||
}
|
||||
result = strings.TrimSpace(result)
|
||||
return ioutil.WriteFile(path, []byte(result), os.ModePerm)
|
||||
}
|
||||
|
||||
|
||||
@@ -141,23 +141,26 @@ func createGoModFileIfNeed(dir string) {
|
||||
}
|
||||
|
||||
_, hasGoMod := util.FindGoModPath(dir)
|
||||
if !hasGoMod {
|
||||
gopath := os.Getenv("GOPATH")
|
||||
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)
|
||||
}
|
||||
if hasGoMod {
|
||||
return
|
||||
}
|
||||
|
||||
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 {
|
||||
ctx context.Context
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
logx.Logger
|
||||
}
|
||||
|
||||
func New{{.logic}}(ctx context.Context, svcCtx *svc.ServiceContext) {{.logic}} {
|
||||
return {{.logic}}{
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
Logger: logx.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *{{.logic}}) {{.function}}({{.request}}) {{.responseType}} {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
{{.returnString}}
|
||||
}
|
||||
`
|
||||
|
||||
@@ -22,7 +22,7 @@ func getParentPackage(dir string) (string, error) {
|
||||
}
|
||||
|
||||
absDir = strings.ReplaceAll(absDir, `\`, `/`)
|
||||
var rootPath, hasGoMod = goctlutil.FindGoModPath(dir)
|
||||
rootPath, hasGoMod := goctlutil.FindGoModPath(dir)
|
||||
if hasGoMod {
|
||||
return rootPath, nil
|
||||
}
|
||||
@@ -32,7 +32,7 @@ func getParentPackage(dir string) (string, error) {
|
||||
pos := strings.Index(absDir, parent)
|
||||
if pos < 0 {
|
||||
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:]
|
||||
} else {
|
||||
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 {
|
||||
var authNames = collection.NewSet()
|
||||
authNames := collection.NewSet()
|
||||
for _, g := range api.Service.Groups {
|
||||
if value, ok := util.GetAnnotationValue(g.Annotations, "server", "jwt"); ok {
|
||||
authNames.Add(value)
|
||||
@@ -78,5 +78,6 @@ func formatCode(code string) string {
|
||||
if err != nil {
|
||||
return code
|
||||
}
|
||||
|
||||
return string(ret)
|
||||
}
|
||||
|
||||
@@ -9,14 +9,9 @@ import (
|
||||
|
||||
func DockerCommand(c *cli.Context) error {
|
||||
goFile := c.String("go")
|
||||
namespace := c.String("namespace")
|
||||
if len(goFile) == 0 || len(namespace) == 0 {
|
||||
return errors.New("-go and -namespace can't be empty")
|
||||
if len(goFile) == 0 {
|
||||
return errors.New("-go can't be empty")
|
||||
}
|
||||
|
||||
if err := gen.GenerateDockerfile(goFile, "-f", "etc/config.json"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return gen.GenerateMakefile(goFile, namespace)
|
||||
return gen.GenerateDockerfile(goFile, "-f", "etc/config.yaml")
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
@@ -9,11 +10,16 @@ import (
|
||||
)
|
||||
|
||||
func GenerateDockerfile(goFile string, args ...string) error {
|
||||
relPath, err := util.PathFromGoSrc()
|
||||
projPath, err := getFilePath(filepath.Dir(goFile))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pos := strings.IndexByte(projPath, '/')
|
||||
if pos >= 0 {
|
||||
projPath = projPath[pos+1:]
|
||||
}
|
||||
|
||||
out, err := util.CreateIfNotExist("Dockerfile")
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -28,7 +34,7 @@ func GenerateDockerfile(goFile string, args ...string) error {
|
||||
t := template.Must(template.New("dockerfile").Parse(dockerTemplate))
|
||||
return t.Execute(out, map[string]string{
|
||||
"projectName": vars.ProjectName,
|
||||
"goRelPath": relPath,
|
||||
"goRelPath": projPath,
|
||||
"goFile": goFile,
|
||||
"exeFile": util.FileNameWithoutExt(goFile),
|
||||
"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
|
||||
|
||||
const (
|
||||
dockerTemplate = `FROM golang:alpine AS builder
|
||||
const dockerTemplate = `FROM golang:alpine AS builder
|
||||
|
||||
LABEL stage=gobuilder
|
||||
|
||||
@@ -26,19 +25,3 @@ COPY --from=builder /app/{{.exeFile}} /app/{{.exeFile}}
|
||||
|
||||
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 {
|
||||
os := runtime.GOOS
|
||||
switch os {
|
||||
case "darwin", "windows":
|
||||
case "darwin", "linux", "windows":
|
||||
default:
|
||||
logx.Must(fmt.Errorf("unexpected os: %s", os))
|
||||
}
|
||||
|
||||
@@ -12,13 +12,14 @@ func Run(arg string) (string, error) {
|
||||
goos := runtime.GOOS
|
||||
var cmd *exec.Cmd
|
||||
switch goos {
|
||||
case "darwin":
|
||||
case "darwin", "linux":
|
||||
cmd = exec.Command("sh", "-c", arg)
|
||||
case "windows":
|
||||
cmd = exec.Command("cmd.exe", "/c", arg)
|
||||
default:
|
||||
return "", fmt.Errorf("unexpected os: %v", goos)
|
||||
}
|
||||
|
||||
dtsout := new(bytes.Buffer)
|
||||
stderr := new(bytes.Buffer)
|
||||
cmd.Stdout = dtsout
|
||||
@@ -30,5 +31,6 @@ func Run(arg string) (string, error) {
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
return dtsout.String(), nil
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ func (g *defaultRpcGenerator) mustGetPackage(dir string) string {
|
||||
switch os {
|
||||
case "windows":
|
||||
relativePath = filepath.ToSlash(relativePath)
|
||||
case "darwin":
|
||||
case "darwin", "linux":
|
||||
default:
|
||||
g.Ctx.Fatalln("unexpected os: %s", os)
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@ import (
|
||||
)
|
||||
|
||||
const etcTemplate = `Name: {{.serviceName}}.rpc
|
||||
Log:
|
||||
Mode: console
|
||||
ListenOn: 127.0.0.1:8080
|
||||
Etcd:
|
||||
Hosts:
|
||||
|
||||
@@ -22,13 +22,15 @@ import (
|
||||
)
|
||||
|
||||
type {{.logicName}} struct {
|
||||
ctx context.Context
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
logx.Logger
|
||||
}
|
||||
|
||||
func New{{.logicName}}(ctx context.Context,svcCtx *svc.ServiceContext) *{{.logicName}} {
|
||||
return &{{.logicName}}{
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
Logger: logx.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user