技术阅读周刊,每周更新。
历史更新
20231122:第十一期
20231129:第十二期
20240105:第十三期:一些提高生产力的终端命令
20240112:第十四期:Golang 作者 Rob Pike 在 GopherConAU 上的分享
How I write HTTP services in Go after 13 years
使用NewServer函数构建服务实例,利用依赖注入方式将所有的依赖参数包含进来。
func NewServer(logger *Loggerconfig *ConfigcommentStore *commentStoreanotherStore *anotherStore
) http.Handler {mux := http.NewServeMux()addRoutes(mux,Logger,Config,commentStore,anotherStore,)var handler http.Handler = muxhandler = someMiddleware(handler)handler = someMiddleware2(handler)handler = someMiddleware3(handler)return handler
}
在routes.go文件中统一定义所有路由函数。
func addRoutes(mux *http.ServeMux,logger *logging.Logger,config Config,tenantsStore *TenantsStore,commentsStore *CommentsStore,conversationService *ConversationService,chatGPTService *ChatGPTService,authProxy *authProxy
) {mux.Handle("/api/v1/", handleTenantsGet(logger, tenantsStore))mux.Handle("/oauth2/", handleOAuth2Proxy(logger, authProxy))mux.HandleFunc("/healthz", handleHealthzPlease(logger))mux.Handle("/", http.NotFoundHandler())
}
主函数只调用run函数来运行服务
func run(ctx context.Context, w io.Writer, args []string) error {ctx, cancel := signal.NotifyContext(ctx, os.Interrupt)defer cancel()// ...
}func main() {ctx := context.Background()if err := run(ctx, os.Stdout, os.Args); err != nil {fmt.Fprintf(os.Stderr, "%s\n", err)os.Exit(1)}
}
返回闭包 handle
// handleSomething handles one of those web requests
// that you hear so much about.
func handleSomething(logger *Logger) http.Handler {thing := prepareThing()return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {// use thing to handle requestlogger.Info(r.Context(), "msg", "handleSomething")})
}
定义通用的encode和decode函数
func encode[T any](w http.ResponseWriter, r *http.Request, status int, v T) error {w.Header().Set("Content-Type", "application/json")w.WriteHeader(status)if err := json.NewEncoder(w).Encode(v); err != nil {return fmt.Errorf("encode json: %w", err)}return nil
}func decode[T any](r *http.Request) (T, error) {var v Tif err := json.NewDecoder(r.Body).Decode(&v); err != nil {return v, fmt.Errorf("decode json: %w", err)}return v, nil
}
提供一个抽象的 Validator 接口用于验证
// Validator is an object that can be validated.
type Validator interface {// Valid checks the object and returns any// problems. If len(problems) == 0 then// the object is valid.Valid(ctx context.Context) (problems map[string]string)
}func decodeValid[T Validator](r *http.Request) (T, map[string]string, error) {var v Tif err := json.NewDecoder(r.Body).Decode(&v); err != nil {return v, nil, fmt.Errorf("decode json: %w", err)}if problems := v.Valid(r.Context()); len(problems) > 0 {return v, problems, fmt.Errorf("invalid %T: %d problems", v, len(problems))}return v, nil, nil
}
自定义校验需要实现 Validator
接口。
使用 Once 延迟调用来提高启动性能。
func handleTemplate(files string...) http.HandlerFunc {var (init sync.Oncetpl *template.Templatetplerr error)return func(w http.ResponseWriter, r *http.Request) {init.Do(func(){tpl, tplerr = template.ParseFiles(files...)})if tplerr != nil {http.Error(w, tplerr.Error(), http.StatusInternalServerError)return}// use tpl}
}
What is OpenTelemetry?
这是一篇 OTel 的科普文章
OpenTelemetry 提供一个统一、可扩展的框架,用于收集、分析和观察分布式系统的性能数据。它包括一组API、库、代理和收集器,这些组件可以跨多种编程语言和平台实现对应用程序的监控。
OpenTelemetry 整合 OpenTracing 和 OpenCensus。
2019年,两个社区进行了合并。
同时 OTel 具备以下特征:
统一性:OpenTelemetry 提供了一个统一的API,使得开发者可以在不同的编程语言和框架中以一致的方式实现监控。
可扩展性:可以编写自己的扩展来满足个性化需要
跨平台:OpenTelemetry 支持多种编程语言,如 Java、Python、Go、.NET 等,以及多种云服务和容器平台。
社区驱动:作为一个开源项目,OpenTelemetry 由一个活跃的社区支持,社区成员贡献代码、文档和最佳实践。
与现有工具的兼容性:OpenTelemetry 设计时考虑了与现有监控工具的兼容性,如 Prometheus、Jaeger、Zipkin 等,这使得它可以轻松地集成到现有的监控基础设施中。
提供了一种名为:OTLP(OpenTelemetry Protocol)的通讯协议,基于 gRPC。
使用该协议用于客户端与 Collector 采集器进行交互。
Collector 是 OpenTelemetry 架构中的一个关键组件,它负责接收、处理和导出数据(Trace/log/metrics)。
它可以接受从客户端发出的数据进行处理,同时可以导出为不同格式的数据。
总的来说 OTel 是可观测系统的新标准,基于它可以兼容以前使用的 Prometheus、 victoriametrics、skywalking 等系统,同时还可以灵活扩展,不用与任何但一生态或技术栈进行绑定。
Popular git config options
本文总结了一些常用的 git 配置
pull.ff only
或pull.rebase true
:这两个选项都可以避免在执行git pull
时意外创建合并提交,特别是当上游分支已经发生了变化的时候。merge.conflictstyle diff3
:这个选项使得合并冲突更易于阅读,通过在冲突中显示原始代码版本,帮助用户更好地解决冲突。rebase.autosquash true
和rebase.autostash true
:这些选项使得修改旧提交变得更容易,并且自动处理stash。push.default simple
或push.default current
:这些选项告诉git push
自动推送当前分支到同名的远程分支。init.defaultBranch main
:创建新仓库时,默认创建main
分支而不是master
分支。commit.verbose true
:在提交时显示整个提交差异。rerere.enabled true
:启用rerere
功能,自动解决冲突help.autocorrect
:设置自动矫正的级别,以自动运行建议的命令。core.pager delta
:设置Git使用的分页器,例如使用delta
来查看带有语法高亮的diff。diff.algorithm histogram
:设置Git的diff算法,以改善函数重排时的diff显示。
文章链接:
https://grafana.com/blog/2024/02/09/how-i-write-http-services-in-go-after-13-years/
https://codeboten.medium.com/what-is-opentelemetry-6a7e5c6901c5
https://jvns.ca/blog/2024/02/16/popular-git-config-options/
往期推荐
【译】Apache Pulsar 3.2.0 发布
我的 2023
手把手教你为开源项目贡献代码
得物云原生全链路追踪Trace2.0架构实践
点分享
点收藏
点点赞
点在看