in-source builds or out-source builds

最近一段时间在跟进解决一系列的跟编译相关的事情,发现大家特别喜欢在源码目录直接编译代码,功能角度上这没有什么问题,但从源码管理角度来看这种方式还是存在很多不好的地方,最直观的感受就是一堆凌乱的编译中间文件。那么为什么我们应该选择out-source builds而不是in-source builds呢?(这篇文章列得很详细http://voices.canonical.com/jussi.pakkanen/2013/04/16/why-you-should-consider-using-separate-build-directories/)

1. 易于清理
这个是最容易理解也最显而易见的,一堆中间临时文件,干扰你阅读源码,干扰你打包源码tree,干扰你清理编译中间文件。

2. 可以针对不同的编译选项设立独立的编译目录
这样的好处显而易见,可能做测试,可能给不同类型的用户使用,需要多套不同的编译选项,这样in-source builds就不能满足要求了。

3. 可以对源码目录和编译目录做特定控制或优化
比如源码不允许修改(只读),或者需要加速编译,可能会把编译目录放到更快速的存储设备上。

原创文章,转载请注明: 转载自下雨天
本文链接地址: in-source builds or out-source builds

QR:  in-source builds or out-source builds

向目标文件注入编译环境信息

【背景】
前段时间一个离职同事几年前的老模块需要交接,由于长时间无人维护,一时找不到代码路径,只得从整个后台中心的代码库里面“人肉“。记得曾经还出现过类似的情况,找不到老的编译环境(现有的系统,机器都升级了),被迫重构了老代码。工作时间越长,这样的问题也就会越来越频繁,老是这么死板的处理也不是个办法,费时费力,苦不堪言。如果可以将server部署前的编译环境信息集成到目标文件中,是否就可以根据线上运行的目标文件定位到相关的信息呢?目前部门的开发方式都是依赖于框架,所以只得在框架上下功夫。定好2个核心原则,撸起袖子就是干:对开发者透明,能便捷的获取信息。

【实现】
整个框架的编译体系是通过cmake维系的,通过其丰富的能力可以实现一些特殊的功效。框架使用gflags来维护命令行参数,本已经集成一些基本的参数,比如threads, conf,pid_file等,所以直接通过这种方式来获取编译环境信息对开发者更加熟悉和便捷。
1. cmake获取编译环境信息。

2. cmake将信息string以宏的方式透传给框架头文件。

3. 框架头文件使用宏来区分框架编译和业务编译。

4. 运行效果。

 

 

原创文章,转载请注明: 转载自下雨天
本文链接地址: 向目标文件注入编译环境信息

QR:  向目标文件注入编译环境信息

控制cmake查询路径

【背景】
部门依赖特定框架开发代码,框架中已经集成了protobuf,但是用户却有可能在开发机上胡乱安装protobuf。而业务链接到的版本是框架的protobuf,但cmake中find_package(Protobuf)默认的是用系统protobuf中的protoc编译描述文件,当系统中pb和框架pb版本不同时,就会造成编译错误。

【构思】
研究了下Cmake中的FindProtobuf.cmake文件,_protobuf_find_libraries|_protobuf_find_libraries|_protobuf_find_libraries中查找lib,include,bin均是通过find_path,find_program,find_library来完成的,只要控制查找路径即可。

于是,框架的xxx-config.cmake中添加一下两行解决问题。业务依赖框架时find_pakcage(xxx)就会自动设置cmake的路径变量,最终达到控制查询结果的目的。

 

原创文章,转载请注明: 转载自下雨天
本文链接地址: 控制cmake查询路径

QR:  控制cmake查询路径

框架自动化部署

【背景】
部门框架是需要部署到开发机上的,框架的更新一直是手动到每台开发机上去更新部署,开发人员和开发机多了之后,框架维护人员已经很难管理住所有开发机的框架环境了。

【构思】
一切只围绕一个目的:在框架有更新时能够更新开发机的框架环境。总体思路是利用CMAKE的ExternalProject_Add来维护项目的编译,crontab来保证检查执行:设定最新的tag_url(如果与历史svn_url不一样就svn switch),svn up + cmake + make。

 

【后续】
现在能够自动更新了,后面最好能够呈现开发机框架视图,所以还需要上报本机的框架环境信息,在服务端呈现出来。

原创文章,转载请注明: 转载自下雨天
本文链接地址: 框架自动化部署

QR:  框架自动化部署

glog FATAL日志写多次的问题

【背景】
LOG(FATAL)能够使代码更加简洁,在项目中用得比较多。但实际真正触发的时候,看日志总感觉没有写进去。去日志目录观察,实际上是写了两份日志,而当前的日志软连接链到了空日志文件上。这在日志目录下日志文件比较多时,查看上一次挂掉的日志非常不方便。
glog原始情况

【研究】
实际上阅读glog代码发现SendToLog这个函数在打印完所有日志之后,针对FATAL级别的日志,又重新写了一次,而且时间戳是0即(19700101-080000)。

 【解决】
注释掉该段代码搞定。
glog-after-fix

原创文章,转载请注明: 转载自下雨天
本文链接地址: glog FATAL日志写多次的问题

QR:  glog FATAL日志写多次的问题

监控的盲点

【背景】
公司已经有较为完善的监控手段。monitor,通过累积量等一维数据监控自身的情况;智能监控,通过多维数据统计成功率和时耗。当然我们一直认为“一切尽在掌握”。

【问题】
某业务B_T的调用方发现出现超时的情况,排除网络问题,在我们看来只可能是后端服务S_T出问题了。而后查询对应的后端自身服务monitor监控正常,智能监控也变化ok。最后经后端童鞋深入排查,发现是自己server假死了。那么问题来了:
1) 为啥监控没啥变化
假死的server,在LB里面权重被放低了,所以请求量就少了,咋眼看去,monitor视图请求量几乎没变化(减少的很小),因此没有产生告警。而因为假死,所以正常的请求并未被S_T处理,所以智能监控不会被上报,成功率和时耗没有变。
2) 为啥其他业务没太大影响
S_T为很多业务服务,量大的服务,由于成功率都很高,所以通常不会有告警。而量小的业务(或者长尾业务)却很容易受到波动。
3) 为啥没有被LB完全踢掉
这个跟后端S_T的异常姿势有关系,由于是假死,偶尔处理一个请求,LB探测到S_T还alive,又会扔正常的业务数据过来,挂一会儿,又踢掉,周而复始。

【思考】
虽说根本上是后端的server开发者的问题,但是后台开发,监控为王。没有完美的程序,只有不完美的监控。这里暴露出来监控的一些特点,就是不能简单的通过自身的监控上报来判断服务质量,这样就会存在上诉的盲点,监控应该是一个纵深,立体化的过程。将调用方视角的后端服务质量纳入后端服务的监控范围,整合上下游的监控或许才能更加精准的为后端服务保驾护航。

原创文章,转载请注明: 转载自下雨天
本文链接地址: 监控的盲点

QR:  监控的盲点

记一次负载均衡不生效的问题

【背景】
公司目前使用一种基于调用方反馈来衡量后端服务的负载均衡组件,姑且称之为LB_T。正常情况下后端服务异常都会让调用方将此问题机器M_T踢掉,因为每一次成功的调用,调用方都会上报一个成功状态和时耗用以对后端可用性和负载做统计。

【问题】
但这一次只看到后端一直返回错误,而调用方却仍然再往这台机器发包。在基础组件上没有找到太多蛛丝马迹,而后进一步排查发现后端过载了仍然会向前端回包。这也就解释得通了,LB_T这种LB方式通常后端有回包就会认为是成功。虽然可以特化处理错误码,但为了整体的通用性,修改框架让后端过载时只上报自身服务质量和记录日志,不向前端回包,问题解决。

【思考】
问题虽然解决,但是引发了我们的思考:代码中使用了LB组件就一定能做到负载均衡,异常时能切换能容灾?答案是否定的:
1. 姿势非常关键。每一次请求都必定要对LB进行一次Update。
2. 上下游配合。一定要清楚的知道后端何为异常,对后端足够的了解,相互配合才能达到效果。

 

 

原创文章,转载请注明: 转载自下雨天
本文链接地址: 记一次负载均衡不生效的问题

QR:  记一次负载均衡不生效的问题

没有C++11我们如何实现c++的函数变参

传统的变参方法都是基于上古的VA_ARGS来实现的,c++11引入了变参模板,把编写变参方法的便利度提高了的一个前所未有的高度。re2这个库很好的诠释了C++里面即便没有变参模板,也能做便利的变参实现。

【背景】

FullMatch需要提取匹配到的所有子串,而正则表达式本身的灵活性决定了这里的参数(匹配到的子串)必然是变化的。

【RE2实现】

【使用c++11变参模板的实现】

RE2的变参实现通过整齐的重载operator()来实现,最大支持32个参数,因为只实现了32个重载。
而反观使用C++11的变参模板,则简化了很多代码,且没有参数32的限制。后者的便利性自然是极高的,但是在编译器的通用性上,前者更加通用。在没有C++11的情况下,google::re2又给出了实现变参的很好的一个例子。

原创文章,转载请注明: 转载自下雨天
本文链接地址: 没有C++11我们如何实现c++的函数变参

QR:  没有C++11我们如何实现c++的函数变参

轮server监控的层次

监控是服务的晴雨表,对开发者尤为重要,基本是server上线的标配,主要分两个层次。

1. 标准化监控
这里主要有两类 : 标准化的网络设备(主机监控),例如路由器交换机,通常都可以通过snmp协议采集到(即便是私有的od指标也能从生产商处获得);标准化的服务(中间件监控),例如httpd,nginx,mysql,web页面等等,通过对标准服务的特性采集,例如运行端口,进程名称,日志情况等来配置监控参数。
标准化维度的监控,绝大部分开源软件(zabbix,cacti等)都都能满足。

2. 业务服务监控
具体的业务监控,开源的东东就捉襟见肘了,仅仅少部分场景能通过脚本勉强满足,这就是为什么大部分成熟的互联网公司都有自己的一套或几套监控系统。监控 = 上报 + 绘图 + 告警,监控系统 = 上报api + 视图管理 + 告警管理。这里面又大致分成两大类 : 数据量维度的监控和状态维度的监控。

1). 数据量维度
上报点包括总请求量,总失败量,总成功量,各分支请求量,各分支失败量,各分支成功量,特殊上报量,时延区间量(例如50ms以下的处理请求量等)。
数据量是业务监控的最低层次,各项指标不正常,server必然是有问题,但指标正常并不代表server没有问题。

a) server嵌入上报api,monitor_api(int attr_id, int attr_value)
b) monitor_agent周期汇总本机的所有的attr_id的上报值发送给collect_svr
c) collect_svr对数据做处理,按(attr_id, report_ip) -> attr_value存储数据,按attr_id -> report_ip_list和report_ip -> attr_id_list存储索引关系
d) 页面上根据数据和索引关系聚合出各种视图 (attr_id, report_ip, day_timeline),(attr_id, all_report_ip, day_timeline),(report_ip, attr_id_list, day_timeline)
e) 告警模块中针对各个视图关系设置最大值/最小值等告警策略

2). 状态维度
服务的质量通常都是状态量,最常见的指标就是 时延和成功率。这两个指标基本可以反映出某条服务或接口的服务质量。

a) server调用后端结束时嵌入上报api,stat_api(int service_id, int stat_code, uint32_t cost_time)
b) stat_agent周期汇总或者直接转发本机的所有的service_id的上报数据发送给collect_svr
c) collect_svr对数据做处理,按(service_id, called_ip, report_ip) -> stat_value存储数据,按(service_id, called_ip) -> report_ip_list, (service_id, report_ip) -> called_ip_list存储索引
d) 页面上根据数据和索引关系聚合出各种视图 (service_id, report_ip, called_ip_list, day_timeline),(attr_id, called_ip, report_ip_list, day_timeline),(service_id, report_ip, called_ip, day_timeline)
e) 告警模块中对单机或者整个服务的 时延或成功率设置阀值

3. 调用链监控
仅仅是服务自身的监控是不够,还得能够拓扑出一条请求的来龙去脉。这里又分两种:这里业界通用做法都是通过一个traceId贯穿整个调用路径,然后由后端的日志平台离线分析去统计;另外前者必须保证整个公司所有路径都要规范上报,有时候比较困难,局部实现的话,在某一个程序上以调用者的视角去统计所有服务接口的各种信息去上报统计拓扑更容易实施。

原创文章,转载请注明: 转载自下雨天
本文链接地址: 轮server监控的层次

QR:  轮server监控的层次

macbook air在win7下的蓝牙问题

2014年产的macbook air,使用mac下bootcamp安装的win7,然后蓝牙无法使用,这不让我的耳机白买了么,不能忍,各种google各种折腾之后备忘下步骤 :
1. 卸载bootcamp默认蓝牙驱动
2. 驱动之家http://drivers.mydrivers.com/搜索“apple broadcom 蓝牙”下载最新版本
3. 设备管理器中蓝牙设备上右键更新驱动,进入最新版驱动目录查找

原创文章,转载请注明: 转载自下雨天
本文链接地址: macbook air在win7下的蓝牙问题

QR:  macbook air在win7下的蓝牙问题