期待已久的beego2.0来了,最简单易用的企业级应用开发框架

  • Beego 2.0 初心

  • 模块化与解耦

  • AOP 初次尝试

  • 更好的可观测性

    • tracing 和 metrics

    • logging

  • 防呆设计 ORM

  • 姗姗来迟的配置模块优化

  • adapter 模块和升级指南

  • 未来


Beego 2.0 初心

在鸽子精的本性屡次发作之后,我们终于官宣Beego v2.0要和大家见面了。

在得知我们开启了 Beego 2.0 的时候,很多人问我们,你们搞 2.0 干啥呀?

其实不论是 Beego 1.x 还是 Beego 2.0,我们的初心一直没有改变,也就是希望能够为 Go 企业级应用开发提供一种一站式的解决方案,尤其是我们希望能够为中小型企业赋能,帮助这些企业提升研发效率、工程质量,以快速推出新产品,快速完成迭代。

我们很多大型企业都有很多规范,但是我们中小企业在规范和基础组件上面经常是很混乱,开发早期都是怎么快怎么来,但是当有新同学加入或者有一个同学离职,就会导致相同功能不同的写法引入同一功能的不同组件(例如日志引入logrus、zap), 最终会导致维护困难重构难,遇到问题不知道怎么查找问题点,这些都是我们很多企业遇到的困难。

而站在我们打工人的角度,我们也相信,真正的劳动者,不应该是被禁锢在流水线上的囚犯。技术应当解放生产力,将劳动者者从繁琐枯燥的重复性劳动中解放出来,去从事具有创造性艺术性的活动。

所以,我们的设计目标,就是做一个“简单、高效、一站式”的公司统一应用框架。具体而言则是围绕这六个特征进行:

  • 统一标准:让不同层次的工程师可以基于同样的标准写代码;

  • 低代码化:自动生成重复代码,从 CRUD 中解脱出来,专注业务;

  • 错误收敛:设计错误处理标准,大幅提升错误发现、排查和修复的效率;

  • 可治理性:管理应用的生命周期,让应用能够在开发、测试、部署和运维阶段都更简单方便;

  • 可插拔性:自由选择使用的组件,自由接入自己的组件;

  • 可观测性:全方位观测应用,掌握应用的各个方面;

那么,和原先的 Beego 比起来有什么不同呢?让我们一起来看看 Beego 2.0 的几个重大变化吧!

模块化与解耦

在准备着手 v2.0 的时候,我们做了一些调查。一方面是在社区发放调查问卷,一方面是整理 Beego 的 issue,最终我们确认了 v2.0 的总体思路,那就是:模块化,模块化,模块化

其实在 v1.x 的时候,模块化已经有了坚实的基础:

如图所示,很显然 Beego 是由这八个模块组成。而 Beego 被人诟病太重,也是因为 Beego 一个项目就具有这么多模块。而实际上,各个模块即便在 1.x 里面也是相当独立的,只有小部分会耦合在一起。

因此我们要做的是就是重新组织一下这些模块,并且将模块之间的耦合降到最低。

这方面我们参考了几个非常优秀的开源框架,重新划分了我们的模块组织:

正如上图所示,我们希望模块之间只依赖于底层的模块,而互相之间不会依赖。

对于一个企业来说,如果选择 Beego,那么它很容易就统一所有的技术选型(统一标准,扩展组件),并且带来极高的研发效能——这对大多数的中小型企业、初创企业来说至关重要。

AOP 初次尝试

AOP 是一个企业级应用离不开的场景。例如我们想要支持的更好的可观测性,那么在接入诸如 opentracing , prometheus 的时候,就需要这种无侵入式的 AOP 解决方案。

我们思考过几个方案,比如说编译器接口,在编译阶段通过修改 AST 注入特定的 AOP 逻辑;又或者采用代理,但是这需要一个完整的依赖注入框架支持,从开发体验上来讲,也并不是特别好;

从理论上来说,我们喜欢第一种方案,即编译器接口的方案。可惜 Go 并未暴露这种编译器的接口,允许我们在编译过程中修改代码。

在无法使用这些手段的约束下,我们只能折中设计了一个能力有限的无侵入式的 AOP 方案。

那就是使用 filter-chain 的设计模式来完成这一类的 AOP 需求。

具体做法是,我们为主要模块设计了 filter-chain 。这些接口大抵类似,只是参数略有不同。例如在 httplib 中,其接口是:

type FilterChain func(next Filter) Filter
type Filter func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error)

用户很容易可以通过扩展 Filter 接口来完成自定义的功能,例如日志:

func myFilter(next httplib.Filter) httplib.Filter {
    return func(ctx context.Context, req *httplib.BeegoHTTPRequest) (*http.Response, error) {
        r := req.GetRequest()
        logs.Info("hello, here is the filter: ", r.URL)
        // 别忘了调用下一个filter
        return next(ctx, req)
    }
}

这个例子只是记录了一下请求 URL。实际上,如果你要实现熔断限流和容错处理,都可以借助这些 Filter 来完成。

目前,总的来说,AOP 是一个初次尝试的东西。当前的这种机制还不是特别通用。它被局限在一个模块暴露的公共 API 部分,也就是模块入口和出口部分。而且它也不是声明式的。我们所期望的,理想中的 AOP 应当是声明式的,更加贴近 Java Spring 那种声明式 AOP 框架。

更好的可观测性

在 Beego 1.x 中,可观测性三个方面, tacing , metricslogging ,其中 logging 已经得到了很好的支持。

tracing 和 metrics

我们的目标是支持 opentracingprometheus 。选择 opentracing ,是因为它颇有一种业界标准的感觉。大多数有影响力的 tacing 框架,都会考虑提供 opentracing API 的支持。这意味着,用户可以自行选择他们青睐的 tracing 框架,只需要在启动的时候注入特定的实现即可。

promethues 虽然不具备 opentracing API 那种普适性。但是它已经是业界事实上的标准了。

还有一个候选者,就是 opentelemetry 。虽然它号称是下一代的 tracing 标准,但是目前来说,它还不具备 opentracing 那么大的影响力。它自身的实现也很粗糙,因此排除了它。

我们的重点目标是,让使用 Beego 的应用可以实现无缝连接。

例如,假如我用 Beego 同时有 A 和 B 两个应用,而且 A 会调用 B,那么我只需要开启了 tracing 功能,那么我在 A 上使用 httplib 调用 B 的 http 接口,就能实现端到端的链路监控

而实际上,我们也达到了这个目标。例如我测试时候一个效果图,这里我选择了 zipkin 作为 opentracing 的实现:

logging

logging 方面,这一次我们也加进去了一个呼声很高的特性——自定义日志格式。自定义日期格式是一个很实用的功能,一方面是公司可能有日志格式方面的要求,一方面则是更好支持日志分析的需求。当然,品位,或者说个人偏好也一并满足了。

为了降低大家编写自定义日志格式支持的难度,我们额外提供了一个实现 PatternLogFormatter 。例如我们传入一个期望的日志格式 %F:%n|%w%t>> %m 那么最终输出的日志如:

/User/go/beego/main.go:10|2020-12-11[E]>> message

防呆设计 ORM

每次有人问你们为什么要设计新的 ORM 的事务接口?我们都是统一回答:因为用户频繁误用,导致我们回答 issue 不堪其扰。

那么原来的 ORM 有什么弊端呢?

原来的 ORM,如果按照文档来使用,是毫无破绽的。只不过原本的 ORM 是一个有状态的东西,比如说里面有一个 isTx 标记,标记创建的 ORM 对象当前是否处于一个事务中。

然后这就会导致,用户在不同的 goroutine 之中使用同一个 ORM 对象的时候,经常出现并发问题。

这一次我们就改进了这个问题。当然“防呆设计”是一个开玩笑的说法。毕竟一个 API 经常被误用,本身就说明了它在设计上是不够直观的。

我们这一次摒弃了原本维持 isTx 的做法,而是在开启一个事务的时候,返回一个全新的 TxOrm 。这个对象是一次性的,随取随用,用完即丢。

而且,为了减轻手动管理事务的负担,我们提供了一个利用闭包管理事务的 API,用起来很方便:

    err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
        // data
        user := new(User)
        user.Name = "test_transaction"
        // insert data
        // Using txOrm to execute SQL
        _, e := txOrm.Insert(user)
        // if e != nil the transaction will be rollback
        // or it will be committed
        return e
    })

姗姗来迟的配置模块优化

这一次我们在配置模块里面加入了三个很有意思的方法:

 
   Unmarshaler(prefix string, obj interface{}, opt ...DecodeOption) error
   Sub(key string) (Configer, error)
   OnChange(key string, fn func(value string))

说起来这三个方法也只能算是终于把应该有的东西支持了。

不过我们还是想要额外提及一下, Unmarshaler + Sub 简直是神器,能够让用户非常简单的就按照自己的模块组织配置,而后将这些配置反序列化为特定对象。

并且,我们这一次终于迎来第一个远程配置中心的实现 etcd 。用户只需要引入 etcd 的实现,就可以使用了!

其它远程配置中心的支持,欢迎大家来提 PR 啊!

adapter 模块和升级指南

这一次,因为项目结构发生了重大变更。为了减轻升级的负担,我们特意开发了一个 adapter 模块。该模块的结构和原有的结构一样,只不过所有的内部实现都用 2.x 的 API。

用户只需要将包名从 v1.x 的包名换成 adapter 的包名就可以了。

这种替换,我们在 bee 里面也做了支持,只需要执行:

bee fix -t 2

未来

我们的愿景是成为“最简单易用的企业级应用开发框架!”。

接下来我们的工作也会以前面提到的六个特征作为指导,围绕以下方面进行:

  • 统一标准:着重解决当前业务开发测试难的问题,为 ORM 等模块提供便利的测试支持;

  • 错误收敛:为全部组件设计统一的错误码和标准化的错误信息;

  • 可治理性:增强现有的治理功能,例如暴露 cache 的统计信息,模块的错误信息。同时支持 Beego 应用集群维度监控和治理能力;

  • 可观测性:继续在 Beego 内部加多埋点和日志信息,并且允许设定参数开启或者关闭(包括部分开启和部分关闭)。也希望能够提供全面的 benchmark 测试,对所有模块的性能做到心中有数;

技术方向

从技术发展方向而言,我们的三个核心词汇就是:泛型,容器(DI),云原生。

泛型会是我们的第一个目标。因为,每一次泛型出现,都会导致已有的模式发生巨大的变化。例如说现在的 ORM 接口几乎就是只接收 interface 对象,基本上无法享受到编译期的检查。我们也希望我们能够在泛型出来之时,能够迅速抢占技术高地,对外输出我们的实践标准。

容器,包括依赖注入,应用生命周期管理,AOP 方面,会是我们的第二个目标。AOP 这是为了将用户从无聊的创建对象,管理对象和销毁对象中解放出来。而 AOP,前面已经提及了,这是一个做企业级应用开发框架不得不解决的一个问题。

第三个目标云原生则是,探索如何利用好云原生的技术,增强 Beego 应用的可用性、稳定性,减轻对 Beego 应用的运维管理负担。

在此我们先立一个 Flag,希望泛型正式发布的时候,我们已经做好准备了

致谢

感谢这些为 Beego2.0 做出贡献的人员(Github ID):

flycash, jianzhiyao, AllenX2018, IamCathal, tayoogunbiyi, wangle201210, mlboy, askuy, flutterWang, higker,  weirubo, yitea, Cadenguo, unknowon, vinicio, ACrushTest.

还有那些未列出来但是参与我们社区讨论,在 issue 里面给我们提出很多建议的人。

特别感谢 askuy,他可以说是 Beego 2.0 的总架构师,他丰富的经验,使我们更有底气,更有自信。

尤其感谢谢大,为我们把控方向,给予了我们充分的信任,让我们能够在 Beego 里面大展身手。

最后要感谢我们的社区,给了我们很多有用的建议和反馈。以及对我们鸽了好几次的无限包容(我们还是希望你们多来催催我们不然就更加容易鸽了)。

欢迎大家来使用我们 Beego!我们准备了文档和例子,还等什么, 一起来啊!

- 官网: https://beego.me

- 例子 https://github.com/beego/beego-example

- Release Note:https://github.com/beego/beedoc/blob/master/en-US/intro/releases.md

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章