轮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) 告警模块中对单机或者整个服务的 时延或成功率设置阀值


原创文章,转载请注明: 转载自下雨天
本文链接地址: 轮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下的蓝牙问题

yaaf_server的几种结构

总结下不同业务场景下yaaf(yaaf框架是个基于zmq的线程池框架写后台server)server不同的内部结构,大体有以下几种形式:

yaaf框架server结构

 

1. 单一zmq接口的dispatcher+worker(server_1)
早期,部门几乎绝大部分是web业务,中心绝大部分也是cgi+业务server这种形式,当时后台几乎都是面向cgi的,所有逻辑落在worker中,此时业务server的结构是单个zmq_dispatcher + 一组worker的形式。

2.支持多种接口的dispatcher+workerserver_2)
随着业务的增长,与外部门的合作增多,后台server除了给cgi调用之外,还会给诸如客户端提供服务接口 - 原生的udp/tcp/http等,此时框架封装了更多的dispacher负责对接不同来源的调用方,worker仍然保持尽可能的只关注业务逻辑,所以业务server的结构是多个worker_dispatcher + 一组worker的形式。

3.woker_dispatcher+client_dispatcher+worker(server_3)
随着部门越来越大,所做的业务也越来越复杂,后台存在较多的调用更底层服务的情况。此时在server中用框架封装更多的client_dispatcher,用于向后端发请求。worker继续保持尽可能的只关注业务逻辑,这时业务server的结构是worker_dispatcher + client_dispatcher + 一组worker的形式。

4.多组dispatcher+多组worker(server_4)
随着参与业务的增多,越来越多的业务场景出现。当逻辑复杂到一定程度的时候,可能会将dispatcher-worker分组,来方便编写/维护不同的逻辑代码,不同分组内的worker负责模块内相对独立的逻辑,此时的业务server结构是多个dispatcher+ 多组worker。

5.去dispatcher(server_5)
当遇到请求量巨大或者cpu密集型的业务时,dispatcher本身可能成为瓶颈,虽然框架可以平行扩展,但为了榨干单机性能实现上会去掉dispatcher让worker直接对外提供服务,此时的server结构是一组worker。


原创文章,转载请注明: 转载自下雨天
本文链接地址: yaaf_server的几种结构

QR:  yaaf_server的几种结构

zmq自连接问题

【背景】
最近的项目过程中偶然的被同一个问题骚扰:一个基础server挂了(基于zmq的服务),自动拉起的脚本不能成功重启server,查询后发现是监听的端口被绑定了,且是被一个client绑定了,每次都得kill掉那个client然后再重启。

【认知】
经过多方查阅发现是linux的自连接问题,linux允许发生自连接,而zeromq官网也有人提出了这个bug – LIBZMQ-549。那么为神马现网环境的server从来没出现过这个问题呢?因为只有在同一台机器上,client和server五元组才有可能完全相等。

【解决】
1. 保证随机分配的端口与server绑定的端口不重合(/proc/sys/net/ipv4/ip_local_port_range)
2. hack代码,发现ip/port相等立马断开


原创文章,转载请注明: 转载自下雨天
本文链接地址: zmq自连接问题

QR:  zmq自连接问题

用glog打印格式化的日志

glog功能强大自然不必多说,C++下的iostream对象在格式很多的情况下使用非常不方便。cout << xxx << “str1″ << yyyy << “str2″…想着就头疼。由于项目中一直用glog来大日志,所以就开始思考如何用glog打印格式化的日志,glog里面有raw_logging.h的文件支持RAW_LOG(serverty, format_string, var1, var2 …),但细细的看了注释和实际体验之后存在一些问题(it logs straight and ONLY to STDERR w/o buffering): 只支持打印到stderr,由于server程序通常都是守护进程形式运行,终端标准输出和标准错误的描述符都是被关闭了的,使用这个宏就根本打不出日志。于是乎就封装了一层新packString的小接口。

使用的时候,形如:LOG(INOF) << pack_string(“xxx”, int1, “yyy”, str2 …..)


原创文章,转载请注明: 转载自下雨天
本文链接地址: 用glog打印格式化的日志

QR:  用glog打印格式化的日志

mysqlpp编译成静态库

项目中为了方便部署,通常都是将库封装成静态库供实际的server程序链接,但是有些第三方库的编译选项中只提供了动态库,mysqlpp就是其中之一。要么用其他库例如mysqlconncpp,要么就自己改。果断任性的选择了后者。

修改bakefile的配置文件,添加如下片段(类似于cmake的CMakeLists.txt),然后重新生成一遍makefile即可


原创文章,转载请注明: 转载自下雨天
本文链接地址: mysqlpp编译成静态库

QR:  mysqlpp编译成静态库

shell中注入常用工具

开发中经常会用到一些转换,例如时间戳与格式时间,ip字符串和ip整形,大小端等。最早都是跑到相应的工具网站上去进行转换,甚是不便,于是有了…

【第一阶段】
将这几个工具集成到了一个chrome的插件 – devtool。自己用着很方便,但好景不长,新版本chrome禁掉了第三方插件,虽然搞来搞去还是给搞出来了可以用,不过心里已经有了一块疙瘩。

【第二阶段】
linux终端下开发,何不就在终端下的封装一套工具。于是有了一系列的xxxxxx

【第三阶段】
第二阶段用了一段时间,经常忘了命令每次使用又要去查,也有点不便,于是,何不模仿类似的函数种到shell环境里。将工具封装成函数放到shell中,取名尽量用python,c++里面最常见的名字,例如inet_aton/inet_ntoa,htonl/ntohl等,同时用前缀模拟名字空间。


原创文章,转载请注明: 转载自下雨天
本文链接地址: shell中注入常用工具

QR:  shell中注入常用工具

glog崩溃时的堆栈信息添加行号

glog提供了接口可以在程序崩溃时打桩,这里已经能打印基本的堆栈信息,但是没有对应的行号。通过大量的库去解析非常麻烦,而且崩溃时程序一般就要退出了,所以也不在意性能了,所以用一些偏门的方法,比如addr2line去分析出行号。


原创文章,转载请注明: 转载自下雨天
本文链接地址: glog崩溃时的堆栈信息添加行号

QR:  glog崩溃时的堆栈信息添加行号

编译提速实践

【背景】
公司开发机性能太差,随便编译一个普通的项目都要十几秒。

【先验知识】
1. 我们知道ccache和distcc能够缓存部分结果,加速编译
2. 我们还知道make可以利用多核,加快编译

【实践】
1. distcc需要多台机器,部署稍微复杂,因此先将ccache和make用起来。
2. 我们需要无感知的使用这些提速项

==cmake==

==用以下替换掉make==

【效果】
使用后,正常的二次编译时间大致缩短一半。


原创文章,转载请注明: 转载自下雨天
本文链接地址: 编译提速实践

QR:  编译提速实践

扒一扒gcc 4.4下可用的c++0x特性

上帝说要有光,于是就有了光;老大说要有C0x文档,于是就有了这篇文章。
一切按http://gcc.gnu.org/gcc-4.4/cxx0x_status.html官方文档中支持的特性来。

1. 右值
1). 右值基本使用
其实基本不用改变神马,因为支持这些特性的gcc库头文件中都有了对应的右值版本,主要有两种情况。
a) 当参数是右值时,支持的化自动会调用对应的版本来执行。例如 string a = func();
b) 当参数是左值时,用move转成右值再调用。例如 string a = “cxxfsdf”; string b = move(a);
C++类中支持右值的版本,一般出现在类似与复制/赋值构造函数,插入函数(push_back右值版本内部调用emplace_back)等可能与临时对象交互的场景。
2).  4.4上的右值支持还有些蹊跷
文档上说gcc4.4支持右值,但事实上还是有些不一样。

string a = "dfdfdf";
string b = a;
string c = move(a);
vector<uint32_t> a{1,2,3,4};
vector<uint32_t> b = a;
vector<uint32_t> c = move(a);

以上代码,在两套环境中都能正确编译通过。来了个简单的benchmark(以上代码b,c各自循环100W次)。在gcc 4.8下,string和vector的右值版本是能明显看到效率提升的。但在gcc 4.4.7下,string却没差别。打开4.4.7的/usr/include/c++/4.4.7/bits/basic_string.h,没有看到赋值/复制构造函数的右值版本,而4.8的对应的basic_string.h中却有对应的右值版本。继续对照4.4.7的/usr/include/c++/4.4.7/bits/stl_vector.h,不言自明。

#ifdef __GXX_EXPERIMENTAL_CXX0X__ 
      vector(vector&& __x)      
      : _Base(std::forward<_Base>(__x)) { }
...

2.  变参模版
直接上最近项目中用的代码,packString(1213, 11.1, “12121”)。这个特性可以组合出很多简化代码的例子。

template <typename T>;
string packString(const T &value)
{
    stringstream ss;
    ss << value;
    return ss.str();
}
template <typename T, typename... Args>
string packString(const T &value, Args... args)
{
    stringstream ss;
    ss << value << packString(args...);
    return ss.str();
}

3.  统一初始化列表
这个没啥好说的,所有类型都能用{}来初始化,并产生相同的结果。

string a[] = {"1212", "1"};
string b{"1212"};
vector<uint32_t> c{1, 2, 3};

4.  静态断言
编译期(非预编译期)判断,在这个特性之前,框架通过内核宏来模拟编译期断言,现在方便多了。

#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
BUILD_BUG_ON(sizeof(xxxx) == 4)

static_assert(sizeof(xxxx) == 4, "platform no match");

5. 自动推导
1). auto
初始化自动推导类型:以前咱们必须这样std::vector::iterator iter = xxx.begin();现在咱们可以这样auto iter = xxx.begin();语言级别上更智能了,代码可以更精简。
2). decltype
根据表达式推导类型,模版中更强大:decltype(t) b; decltype(a + b + c) dd;

6. 右尖括号
这个算一个小特性,之前两个右尖括号在一起的时候编译会报错,通常要空一个空格,现在ok了。
set<pair<uint32_t,uint32_t> > xx; set<pair<uint32_t,uint32_t>> yy;

7. sizeof扩展
sizeof可以用在类成员身上了。struct to { int d;}; sizeof(to::d);

8. 模版函数支持默认模板参数
之前模版类支持默认模版参数,现在模版函数也能支持到。template <typename T=int> void fc() {};

9. 强类型枚举
虽然使用枚举值的地方同城也可以用整型等来代替,但是这个特性可以更加方便的限定参数,避免出错。

enum tradition_type { t1, t2, t3 };
enum class new_type { nt1, nt2, nt3 };
int a = t1;
new_type c = new_type::nt1;

10. 显式启用或禁用特定的成员函数
简单说就是通过default和delete两个关键字来指明启用或禁用哪些成员函数。之前防止类拷贝喜欢继承boost中的noncopyable类,现在更简洁指明关键字就o拉。

class NonCopyAble
{
    protected:
        NonCopyAble(){}
        virtual ~NonCopyAble(){}
    private:
        NonCopyAble& operator=(const NonCopyAble&);
        NonCopyAble(const NonCopyAble&);
};  
struct NonCopyable {
    NonCopyable() = default;
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable & operator=(const NonCopyable&) = delete;
    int m;
};
/*
NonCopyable a;
NonCopyable b = a;
NonCopyable c;
c = a;
NonCopyable c(a);
*/

11. 并发相关
坑爹的4.4的原子操作头文件是cstdatomic,4.7之后又是标准的atomic头文件了。其他的如thread等都有相应的头文件。这类特性对后台开发最有吸引力,但是在4.4中的支持力度没有看到详细的说明,暂不敢贸然使用。


原创文章,转载请注明: 转载自下雨天
本文链接地址: 扒一扒gcc 4.4下可用的c++0x特性

QR:  扒一扒gcc 4.4下可用的c++0x特性