diff --git a/doc/how_to_parse_args_and_flags_in_goc.md b/doc/how_to_parse_args_and_flags_in_goc.md index c4e9e8b..f90ca31 100644 --- a/doc/how_to_parse_args_and_flags_in_goc.md +++ b/doc/how_to_parse_args_and_flags_in_goc.md @@ -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 的子命令保持一致(两个短横线)。 \ No newline at end of file diff --git a/doc/protocol.md b/doc/protocol.md new file mode 100644 index 0000000..fd52f6b --- /dev/null +++ b/doc/protocol.md @@ -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 + +### 异常处理 \ No newline at end of file diff --git a/doc/return_error_or_fatal.md b/doc/return_error_or_fatal.md index a3bc736..112f0c4 100644 --- a/doc/return_error_or_fatal.md +++ b/doc/return_error_or_fatal.md @@ -1,2 +1,12 @@ # 返回 error 还是原地 fatal +哪种好呢?在一个纯命令行应用中,及时 fatal,并能在 Panic 中打印出堆栈对调试即为有意。 + +若是返回 error,虽然看起来: + +1. 对每种异常处理都定义的很清楚(有明确的错误消息) +2. 写单测也更容易 + +但是 Go 的错误处理,导致 error 被一层层返回,以至于在最上层拿到 error 时你都分不清有几层了 -_-,虽然 Go 1.13 的 error wrap 一定程度消减了这个问题,但还是不如 Panic 来的好调试。 + +而且 goc 并不是一个供大家使用的库,目前来看 fatal 还是更适合。 \ No newline at end of file diff --git a/internal/websocket/client.go b/internal/websocket/client.go deleted file mode 100644 index 46cffd5..0000000 --- a/internal/websocket/client.go +++ /dev/null @@ -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) { - -}