

[Golang]如何优雅的管理几十个UDF(API)
source link: https://studygolang.com/articles/33850
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

组内一个服务中有个叫算子的模块,所谓 算子 可以理解为UDF(User Defined Function),这个模块的核心思想是:在做业务需求时,把业务拆解为几块通用的 业务代码(UDF) ,不同的代码块承担不同的业务功能。这些代码块提供出不同的配置项(或者叫“函数签名”),用户传入对应的参数调用这块代码。
这样做的好处是:后续接业务需求时只需要通过编排算子配置就可以复用通用算子。业务不复杂时,单个算子即可支持业务;业务复杂时,通过多个算子组合为pipeline支持业务。
编个:chestnut:,现在有个业务需求:用户下单后需要统计用户当天完单量,并给下游发送用户的单量消息,下游营销系统根据用户的完单量给用户推送不同的优惠策略。
对整个业务流程做一下抽象:

image.png
这里编排schema和转发MQ都是不涉及存储的纯计算型业务需求。现在把这两个功能抽象成算子:
第一个算子为"编排schema",功能是把各种参数编排成一个string格式的字符串并返回。其配置schema可能长这样:
{ "calc_param": ["user_id", "finish_cnt", "time_stamp"], "calc_options": { "template": "{\"user_id\":\"{{user_id}}\",\"finish_cnt\":\"{{finish_cnt}}\",\"time_stamp\":\"{{time_stamp}}\"}" } }
第二个算子为"发送MQ",功能是把输入的string格式的字符串作为生产者发送到一个MQ中。其配置schema可能长这样:
{ "calc_param": ["last_calc_string_res"], "calc_options": { "topic_name": "an_awesome_topic" } }
把这两个算子组成一个json list,作为一个业务配置,服务读取配置就实现业务需求了,整个过程中不用写一行代码。
理想很丰满,实现很骨感。在实际开发迭代中,由于团队扩张、人员流动、代码注释缺失的问题,算子模块出现了三个问题:
- 有人不知道系统中有哪些通用算子
- 通用算子使用成本较高(测试文件(如果有) or 看算子源码)
- 通用算子维护成本较高(写完代码之后需要写wiki,更新完代码之后需要改wiki)
这两个问题导致的结果是:有的需求可以通过一些通用算子的配置组合支持业务,但是在不熟悉的情况下有的人会选择写一坨"定制算子(全是具体的业务逻辑)"去支持需求。
这么做倒是无可厚非,相比于纯写配置一行代码都不开发而言,一天写300行业务代码支持一个业务可能更会带来成就感,且上线之后也不出Bug就完事了呗,条条大路通罗马嘛;)
但这样做有点不符合组内系统的核心思想,还是应该去建设更加通用的算子,当通用算子积累到一定程度,并以一种合理的方式被管理起来,那最终的业务收益就可能变成这样:RD在平台上通过拖拉拽组合 通用算子 就可以支持业务,在系统建设足够完善的情况下,一人一天支持100个业务需求都不在话下;)
所以现在就有一个不太痛的痛点:需要把算子模块管理起来。如果在基于一开始的设想:
算子 == UDF
那完全可以学习编程语言管理UDF的方式对算子模块进行管理,具体的解决方案为:
痛点 方案 新同事不知道系统中有哪些通用算子 对通用算子打上不同的分类标签:比如上面的 编排schema 算子可以打上"字符串操作" tag;发送MQ 算子 可以打上 "MQ操作"、"外部rpc" tag 通用算子使用成本过高 搞一个算子平台,提供REPL的能力供用户使用算子 通用算子维护成本过高 问题发生的本质原因是:代码与wiki编写过程是剥离的,那就把这两个过程放在一起,把wiki放在代码里,并写一些元编程的代码生成这份wiki。 实际上这个算子模块管理系统是必须的:在系统刚开始迭代时,系统里可能只有几个通用算子,这时你的使用成本很低,这就好比你随时记得你喜欢的Go语言里有 json.Unmarshal
、 json.Marshal
、 http.ListenAndServe
、 strings.Split
这几个系统函数。
但是随着业务的发展,你的系统也会迭代,最终你的代码里可能有几十个、上百个UDF,如果不把算子按照类型管理起来,你就需要随时记忆这么多的UDF,这就好比 你可能并不记得你喜欢的Go语言的strings包里还有一个叫做 EqualFold
的系统函数,即使你有一个模糊的印象,那你使用时候也得去看看wiki里是怎么写的。
对于如何把 代码编写 和 wiki维护 这两个割裂的步骤放在一起,在下有一些不成熟的想法。在这里写一种思路:
对于每一种段子,都抽象出其配置schema和参数schema,所谓的schema在Golang中即结构体,我们在结构体中写多种tag记录各个属性的元信息,并通过反射把这些元信息同步到DB中,元信息落库后,就可以和前端同学合作建立酷炫的管理平台管理算子了。
Go的反射及其不好用,这里简单写一些反射代码,把上文那两个算子配置读取结构体元信息这块表示一下:
package main import ( "fmt" "reflect" ) type MQOption struct { TopicName string `json:"topic_name" comment:"消息队列名称"` } func getStructTag(v interface{}, tag string) { structVal := reflect.ValueOf(v).Elem() structType := structVal.Type() fmt.Println(structType, structVal) for i := 0; i < structVal.NumField(); i++ { fieldType := structType.Field(i) fmt.Println("fieldType", fieldType) field := structVal.FieldByName(fieldType.Name) fmt.Println("field", field) comment := fieldType.Tag.Get(tag) fmt.Println("tag", comment) } } func main() { mo := new(MQOption) getStructTag(mo, "comment") } // ------------ output ------------ // main.MQOption {} // fieldType {TopicName string json:"topic_name" comment:"消息队列名称" 0 [0] false} // field // tag 消息队列名称 // ------------ output ------------
上面这块代码只是玩具,不建议用于生产环境,如果对这块有兴趣,可以去github上找开源项目。
欢迎关注我的公众号:薯条的自我修养
有疑问加站长微信联系(非本文作者)

Recommend
-
57
PySpark is the Spark API implementation using the Non-JVM language Python. Though developers utilize PySpark by implementing Python Code using Spark API’s (Python version of Spark API’s), internally, Spark uses data to be...
-
34
-
11
Integrating Hive UDF's in Python I need to do some pretty flexible things in my Hive queries, so flexible that it’s beyond the capability of Hive QL. Writing a Hive UDF (user defined function) is an option. However, all t...
-
8
Impala 添加和使用 UDF Impala 支持 C++ 和 Java 编写的 UDF, 把对应的 so 或 jar 文件放到 HDFS,再注册一下就能使用。官方推荐使用 C++ 编写 UDF,相比 Java 的实现有 10 倍性能提升。Hive 有丰富的...
-
11
本文转载自微信公众号「Java大数据与数据仓库」,作者刘不二 。转载本文请联系Java大数据与数据仓库公众号。
-
11
UDF overloading in spark Reading Time: 2 minutesUDF are User Defined Function which are register with hive context to use...
-
10
Scalar UDF Inlining Scalar UDF Inlining now available on Azure SQL ...
-
6
1 min read CVE-2021-44521 Apache Cassandra 加载UDF RCE 2022-02-12 代码审计 UDF
-
17
Dar1in9's Blog切换站点概览你已经读了100%mysql udf提权 2022-03-07|渗透字数总计: 14|阅读时长: 1 分钟
-
2
一、MySQL UDF这玩意全称 “MySQL user-definable function”, 从名字就可以看出来叫 “用户定义的方法”; 那么 UDF 到底是干啥的呢?简单一句话说就是说: 你可以自己写点代码处理数据, 然后把这段代码编译成动态链接库(so),...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK