update design doc
This commit is contained in:
parent
18c4c4a2da
commit
dca67829b6
@ -10,7 +10,7 @@ goc build/install/run 会尽可能的模仿 go 原生的方式去处理参数。
|
||||
|
||||
## 主要问题
|
||||
|
||||
1. goc 使用 cobra 库来组织各个子命令。cobra 对 flag 处理采用的是 posix 风格(两个个短横线),和 go 的 flag 处理差异很大(一个短横线)。
|
||||
1. goc 使用 cobra 库来组织各个子命令。cobra 对 flag 处理采用的是 posix 风格(两个短横线),和 go 的 flag 处理差异很大(一个短横线)。
|
||||
2. go 命令中 args 和 flags 有着严格先后顺序。而 cobra 库对 flags 和 args 的位置没有要求。
|
||||
3. 参数中 `[packages]` 有多种组合情况,会影响到插桩的起始位置。
|
||||
4. goc 还有自己参数,且需要和**非** goc build/install/run 的子命令保持一致(两个短横线)。
|
49
doc/protocol.md
Normal file
49
doc/protocol.md
Normal file
@ -0,0 +1,49 @@
|
||||
# 通信协议设计
|
||||
|
||||
## 背景
|
||||
|
||||
v1 版本中,被插桩的服务会暴露一个 HTTP 接口,由 goc server 来访问获取覆盖率。
|
||||
|
||||
该方式要求被插桩的服务要有一个外界可访问的 ip + port。
|
||||
|
||||
如果被测服务躲在 NAT 网络下,该方式就不可行了,典型的就是被测服务由 docker 拉起,而 goc server 部署在另外的网络。
|
||||
|
||||
## 新设计选择
|
||||
|
||||
新设计只需要暴露 goc server 的地址,由插桩服务发起链接,然后保持长链接,在该长链接上构建 goc 自己的业务逻辑。
|
||||
|
||||
### 自行设计 TCP 应用层协议
|
||||
|
||||
go 语言做网络编程非常适合,非阻塞地处理“粘包”也不麻烦。但设计出来不管是纯二进制的、还是类似 HTTP 的,都不会是通用协议,后续维护和扩展估计是个大坑。
|
||||
|
||||
### websocket + jsonrpc2
|
||||
|
||||
websocket + jsonrpc2 有流式调用,消息边界。非常适合
|
||||
|
||||
我找到 `github.com/goriila/websocket` 和 `github.com/sourcegraph/jsonrpc2` 库,后者 import 了前者,前者没有 import 任何其它外部库,全是标准库。把两个库的代码合并一下:`github.com/lyyyuna/jsonrpc2` 就是一个无任何外部库引用的 jsonrpc 实现。
|
||||
|
||||
这非常适合由插桩代码来使用,因为该库没有再引用其它库,**不会污染原服务的依赖关系**。
|
||||
|
||||
### gRPC
|
||||
|
||||
老实说 gRPC 在这里更适合作为通信协议来使用,更快更通用,流式调用也有,上一小节的 `github.com/sourcegraph/jsonrpc2` 使用广度就很低。
|
||||
|
||||
但 gRPC 的 go 实现有一个很大的缺点,用了一些非标准库,且有版本依赖。我们不清楚原服务是不是有特定 gRPC 要求,或是 goc 插入的 gRPC 库会导致编译依赖冲突,或者是编译后运行冲突。
|
||||
|
||||
所以不适合。
|
||||
|
||||
### 结论
|
||||
|
||||
先使用 websocket + jsonrpc2 来做吧。
|
||||
|
||||
## 协议内容
|
||||
|
||||
### 注册
|
||||
|
||||
### 获取覆盖率
|
||||
|
||||
### 清空覆盖率
|
||||
|
||||
### watch
|
||||
|
||||
### 异常处理
|
@ -1,2 +1,12 @@
|
||||
# 返回 error 还是原地 fatal
|
||||
|
||||
哪种好呢?在一个纯命令行应用中,及时 fatal,并能在 Panic 中打印出堆栈对调试即为有意。
|
||||
|
||||
若是返回 error,虽然看起来:
|
||||
|
||||
1. 对每种异常处理都定义的很清楚(有明确的错误消息)
|
||||
2. 写单测也更容易
|
||||
|
||||
但是 Go 的错误处理,导致 error 被一层层返回,以至于在最上层拿到 error 时你都分不清有几层了 -_-,虽然 Go 1.13 的 error wrap 一定程度消减了这个问题,但还是不如 Panic 来的好调试。
|
||||
|
||||
而且 goc 并不是一个供大家使用的库,目前来看 fatal 还是更适合。
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
Copyright 2020 Qiniu Cloud (qiniu.com)
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Dialer contains all options for connecting to a specified websocket server
|
||||
type Dialer struct {
|
||||
Proxy func(*http.Request) (*url.URL, error)
|
||||
HandshakeTimeout time.Duration
|
||||
Subprotocols []string
|
||||
}
|
||||
|
||||
// DefaultDialer is dialer with all necessary fields set to default value
|
||||
var DefaultDialer = &Dialer{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
HandshakeTimeout: 45 * time.Second,
|
||||
}
|
||||
|
||||
func (d *Dialer) Dial() {
|
||||
|
||||
}
|
||||
|
||||
func (d *Dialer) DialContext(ctx context.Context) {
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user