bigflow开源~破茧成蝶

本文会穿插各种技术问题


先对bigflow 做个简单介绍:

Baidu Bigflow Python是一个Python module,利用module中的数据抽象和API,你可以书写自己的计算任务。它提供了一套函数式编程风格的API,同时将这些API串联/级联成为数据流管道(bigflow pipeline)。Bigflow Python能够将Pipeline映射成为不同分布式计算引擎上的计算任务,例如(Spark,目前开源版本只支持local模式和spark模式),极大地简化分布式计算程序的编写和维护。
使用Bigflow Python主要的收益有:

  • 简单易用的API
    Bigflow Python提供了对分布式数据和计算的高层抽象API,易学易懂;同时作为一个Python module,你可以在Python交互Shell中使用它。
  • 任务自动优化
    所有的计算均为惰性求值(lazy evaluation),Bigflow Python能够看到尽可能大的计算过程并进行关键参数的自动优化,使用Bigflow Python写出的任务能够与那些对特定引擎非常有经验的程序员相当。
    在百度公司内部使用情况来看,Bigflow比用户手工实现的作业性能提升50%~200%。Bigflow开源版本Benchmark正在准备中,敬请期待。

介绍完bigflow,让时间回到一个月前~

当时团队在一起把排期一碰,开始了一场新的征程。

对于项目来说,最重要的两件事是:
一是编译通过&&跑通集成测试,二是优化用户体验。

编译

protobuf问题

遇到的第一个问题是protobuf version的问题。spark 自己的protobuf version 是2.5.0,其他的有用到的版本有2.4.1,有3.x.1。出现了一个问题是3.4.1编译出的 xx.pb.cc, xx.pb.h,被用到了2.4.1中。

最后统一成了2.5.0。解决问题。

顺便还解决了一个问题 java/scala包(A)的protobuf依赖问题。 我们提供了一个c++的so, 然后用A包,去调用so里的函数,但A包里没有protobuf的依赖,需要用spark的protobuf依赖。

之前用的是2.4.1的egg包。后改成protobuf-2.5.0-py2.7.egg
因为我们的protoc 用的是2.5.0的。*.py, .c,.java 等都是其生成的,要对应使用这些文件的程序,必须依赖protobuf 2.5.0.

fPIC

我们编译so,但有一些依赖没有加fPIC。然后添加fPIC。 最难搞的是hdfs的lib,并没有添加fPIC编译参数。然后只能改CMakeLists.txt——`add_compile_options(-fPIC -fpermissive)。

代码漏合

有些代码由于合并方式选择不太对,导致代码漏合。
后面会说一下整体的解决方案。目前问题还不是太大,只是个别文件,所以先手动合并了一下。

thrift

thrift 下载很慢,以及版本不统一。
更换为清华的镜像,并统一为0.9.1版本。

依赖python统一

之前依赖python,分不清楚是依赖的系统的还是自己thirdparty。担心后面同样会带来不可预期的问题。然后把统一改为依赖thirdparty中python2.7,并改为动态依赖。

去 Profiler util 相关代码

目前开源版本并没有添加相关优化,讨论了下,先去掉,后面在考虑添加。

一次编译一个新包

保障更新的代码会被更新到使用tar里面。因为一旦发现包没有完全更新,整个流程就得重新走一边。

这样做可以大大降低成本。

集成测试

spark 集群问题

运行时发现java报错为高版本编译出的结果在低版本jre上运行。
我们编译用的java 是1.8.x的,是那个程序用的是1.7.x一开始没有找到。
这里面有一个大坑是spark web页面上显示的是1.8.x,但实际上是1.7.x。
登录机器发现,yarn 运行是1.7.x。这个是写死在yarn-env.sh中的。这个真的是个大坑哈~~

改了之后,解决问题~

厂内外 hadoop put 的差异

提交作业时,发现报目录不存在。 然后定位发现是:

场内的hadoop put 当目录不存在时,会先创建目录。而社区的需要提前创建目录,再put。

解决方案:在put前,检查目录是不是存在,不存在则用mkdir先创建。

libflpyrt 名字变更

由于libflpyrt.so 和厂内保持不一致导致,作业无法运行。

spark.executor.extraLibraryPath

运行时发现找不到对应的lib库,定位后,发现spark.executor.extraLibraryPath 设置有问题,发现和厂内版本不一致。 也是代码合并时,漏合了。

static 静态变量初始化问题

  • 背景:
    我们的libbflpyrt.so 需要被加载到spark中运行,so中需要初始化python interpreter。 这个初始化。本需要在spark executor main函数中执行,但是main函数在spark中,无法修改。 以前的做法,是在static 静态变量初始化时,完成python interpreter的初始化。
  • 问题:
    python interpreter 初始化时,需要用到gflags、glog的库,而这些库,并没有别初始化。
  • 方案:
    对这样的问题,最好是spark executor 提供相关的接口,初步了解了一下,并没有发现。 目前使用相同的方法实现的:
    在task build时,进行初始化,在task release时,进行释放。这样变成了task级别。

问题暂时得到了解决,但在后面跑case的过程中,出现了不可预期的问题——id()函数不可被调用。

这个问题发生,是那么的神奇,感觉简直就是不可思议,完全没有可能。在没有探索之中,想起了之前解决问题时,看到了这么一段话:

Some memory allocated by extension modules may not be freed. Some extensions may not work properly if their initialization routine is called more than once; this can happen if an application calls Py_Initialize()
and Py_Finalize()
more than once.

前面task中,python interper被多次初始化和释放。现在,不就是被多次调用吗,也许就是它,然后改策略为,在task build 中初始化一次, 相当于在main函数中调用初始化。

抽象出一个可以相当于在main函数中调用的全局方式。后面再有这样的调用可以直接添加。至于析构,进程都没有了,随它去吧~

后面继续寻求更优雅的方式。

还有个问题,虽然现在没有了,也记录一下:

中间还遇到interpreter 在析构时,遇到protobuf c 已经析构的问题。本质上也是一个静态变量析构顺序的问题,protobuf 在 interpreter 之前释放了。
解决方法:
protobuf-2.5.0-py2.7.egg中有两种实现方式,c和python的实现。
spark提供了一个可以指定protobuf 使用实现语言的接口,我们指定为python.
"spark.executorEnv.PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION":"python"

添加 LINK_ALL_SYMBOLS

在链接时,只会添加用到的符号,在代码中并没有用到的类,并不会添加相应符号。

具体场景是这样的。libA.a 依赖 libB.a 。在libB.a中有Base类 和其子类Sub1、Sub2,还有一个map<str_name,Base*>,子类对应的Base*是在自己的文件中添加到map函数中的。但在libA.a 只有Base *指针, 通过str_name 在map找对应子类(Sub1)的Base*

这样在libA.a并没有用到Sub1, 所以在编译的时候,并没有在把Sub1的符号打到libB.a中,在map中也就没有对应的值,最终导致找不到符号。

一个解决方法,是把符号先都打进来。目前用的是这个。

但感觉应该会有更优雅的方案,后面在了解一下。

注:由于LINK_ALL_SYMBOLS,最终是要打到so里的,就引发了前面介绍的fPIC问题

version 自动生成

为了让用户提交作业更快,bigflow的相关包,并不会每次提交,只有version改变了才会提交。
但每次生成包时,version又没有变化,每次都要手动去生成。这个一旦忘记,成本会很大,很容易出现测试半天,白测的情况。

从手动改成自动生成。

urllib2.urlopen 超时时间。

urllib2.urlopen 需要设置超时时间,但作业跑的时间又不确定,目前先设置为365天。

python 报错not found Default()

因为没有上传,google.protobuf.json_format相关包。

改成了只在使用json_format代码处进行import。这样,json_format相关的函数只会在本地使用,远端并不会调用。

import google.protobuf.json_format as json_format
      res = json_format.Parse(response, service_pb2.VoidResponse())

顺便解决了,google.protobuf.json_format (3.x.x)和protobuf-2.5.0-py2.7.egg的冲突问题。

这里要感谢xianjin的帮助。

hadoop 配置路径

从 conf 变更到etc/hadoop 和场外保持一致。

代码合并

关于厂内外代码合并,这就是一个大坑,之前手动merge,而且还是部分merge,厂外代码也做了修改。导致后续merge无法进行。 而且测试中遇到很多的问题,也是由于merge代码不全导致。

后面还是主席,把厂内的代码做一个patch,然后提交到厂外。这样合并代码的问题才被解决。

开发模式

大家在一个主干上开发,导致有覆盖代码的情况出现。
然后,采用拉本地分支的方式来做:
提交代码:
git push <local branch>:master
更新代码:
git checkout master && git pull origin master && git checkout <local branch> && git rebase master

后面发现pull request 也很不错:
自己拉一个远程分支,提交后,手动创建pull request,可以让他人评审。

优化用户体验

bigflow 站点,中文网站自动生成脚本构建。

sphinx 编译时,报找不到'sphinxcontrib.napoleon'
换成'sphinx.ext.napoleon'即可。

主题没有了,换成了html_theme = 'bizstyle'

友好提示

提醒用户设置 JAVA_HOME、HADOOP_HOME。

其他开源准备工作

  • doc 目录变更到根目录下。
  • 修改example,保障正常运行。
  • 删除 dw 等无关代码
  • 添加 license文件 和在源文件中添加 copyright
    • 功能太复杂,用sed 就是一个大坑。 可以考虑sublime,神器。

bigflow 开源版本运行问题基本完成。优化用户体验工作已经做了部分,后面还有需要继续完善。

感谢

感谢jianwei支持
感谢yuncong给予了许多帮助。
感谢 lilishanhui并肩协作以及前期准备。
感谢xianjin 帮忙定位google.protobuf.json_format 等问题。
感谢gonglin 帮忙值周。

感谢团队中每个一起并肩奋斗的伙伴~

小结

bigflow 开源,已经踏出了第一步。

星星之火,开始燎原~

附录

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容