libuv访问mysql_闲聊c/c++ 4: 征服优雅、高效的Libuv库之初识篇

这一系列文章主要分析nodejs中的核心库Libuv。

我的参考书:

朴灵的深入浅出nodejs

Jeffrey Richter的Windows核心编程

Anthony Williams的C++并发编程实战

reference.png

暂定为四篇:

1) 征服之初识篇(背景基础以及重要的概念,图示)

2) 征服之进展篇(libuv的编译,例子,内部用到的c语言技巧以及QUEUE的使用)

3) 征服之高潮篇(线程池,iocp,同步,并发,线程间的通信等)

4) 征服之和谐篇(Libuv的初始化,主循环,主线程和线程池之间的和谐交往)

通过征服Libuv系列文章,目的是让大家了解:

1) C语言之美(语法简单,功能强大,贴近硬件,适合系统级别编程,有很多技巧)

2) 多线程与线程的同步技术

3) 线程池技术

4) windows IOCP技术

5) 了解与ms PPL, intel TBB以及libdispatch(ios gcd)之间的异同点和优缺点。

6) vs c++中多线程下的debug技巧

之所以称为了解,而不是掌握,是因为这些技术偏向于底层的系统编程,并不是一撮而就的,需要一定的时间和经历才能沉淀下来的。因此只能说是让大家了解。

为了简单期间,一些限制条件:

仅关注windows下的实现

仅重点分析libuv的通用cpu密集型计算的框架,了解cpu密集计算框架,实际上异步io就比较容易理解了

因为windows下,异步io通过IOCP(完成端口),会使代码实现非常简单,而效率非常高。

在写此篇blog时,突然感觉到,是不是应该将libuv库进行拆分,将核心部分代码抽离出来单独运行,这样的好处就是要分析的代码量要少很多,仅关注我们感兴趣的代码,有利于演示。

还有一个目的:

就是在简化精华版的基础上升级一下,看看是否能够实现任务的动态均衡(ms PPL库和intel TBB库都有动态均衡,Work Stealing的功能,libuv目前确定没有此功能,libdispatch目前没发现,源码正在阅读中,还没看到)。这个实现难度还是很大的,就当练练手吧,哈哈

我尝试一下吧,看看是否可行!

1、背景:

前段时间,完成了一个微信项目,在后台选型过程中,花了将近一个月考察了java,php几个库,但最终却选择了nodejs,原因很简单:

1、java的配置实在是太麻烦了

2、php实在不熟悉,特别扭

3、nodejs使用js编程,我本人还是比较熟悉js的基础部分(不算es6.0 es7.0标准),并且npm真好用,实在是资源太丰富了,有时选择太多也是一种痛苦啊!

4、nodejs基于异步io技术,效率非常高。而且分布式部署简单。

通过无数次的比较,最终选定了令我非常满意的组合,感觉最起码少写了80%的代码。

后台配套方案:

framework: strongloop/loopback(被IBM收购了,只能说强大无比)

朴灵的: wechat / wechat-api / wechat-oauth

supersheep: wechat-pay

数据库: mongodb用于不需要事务处理的表 mysql用于支付的事务处理

因为没经验,在支付时需要事务处理,所以调整为使用mysql。不过从另外一个角度说明loopback的强大,支持多数据源的统一api操作。

前台配套方案:

总体而言,该前后台配套系统的开发非常令人愉悦。前台不好统计,但是微信后台,至少少写了80%代码!!

我正在做loopback方面的demo,来分享一下loopback框架和angularjs之间的互动,你会看到他们的配合是多么的默契。

近期会有blog以及demo提交github

2、演变:

目前基于异步回调的开发非常盛行,例如ios中的gcd,android中的基于接口回调方式。如果有过这些开发经验,你会觉得nodejs的异步事件开发模型还是蛮熟悉的。

随着逐渐熟悉nodejs,深深的喜欢上了nodejs,因此更想深入的了解一下nodejs是如何实现的。

通过了解nodejs的代码结构,结合深入浅出nodejs第三章的异步io所示流程图,逐步验证其正确性。特别是看到libuv中具有深厚c语言功底的老鸟所写的代码,忍不住想与大家分享c的代码之美!!

题外话:我深入研究过的或正在研究的以及即将研究的c源码库

随便说一下:现在c/c++貌似不太流行了。但是不管如何,c语言我认为是一门基础语言,每个程序员如果想要深入了解底层,最好学一下c语言。

我本人很喜欢c语言,曾经花了5年以上的时间自己研究3D游戏之父-约翰卡马克的quake系列引擎以及sgi opengl1.21实现(This is SGI's Sample Implementation of the OpenGL API. It is both a reference implementation and a driver framework used by **almost all commercial 3D hardware vendors **to develop hardware drivers for their systems)。

可以说quake引擎以及opengl源码是形成我科学程序观的基石,是技术源。(差点说成科学发展观了,这个太....)

目前正在阅读调试的c库源码:

libdispatch ios gcd中的函数都是来源于libdispatch,目前已经都移植到linux和windows中了

libuv 跨平台的异步io和work库

已编译并运行过demo,计划要阅读的c源码库:

libkqueue 一个跨平台的unix kqueue实现。实际在libdispatch移植到windows和linux版本时,就包含了libkqueue。因为libdispatch(源于macos和ios,他们都是基于unix系统的)基于kqueue实现。

libzmq跨平台的异步消息队列库(内部c++实现,以c api方式导出,很多库也使用这种方式)

zookeeper是一个分布式应用程序协调服务,是Hadoop和Hbase的重要组件。目前作为单独一个库独立出来了。

libuv目前基本了解整个流程了,其他几个等弄明白了,也一起分享吧,让我们一起来学c语言!

为什么选这些库:

1) 提高自身编程水平最好的方式是多阅读经典源码

2) 多线程,异步以及分布式、异步消息队列等都是目前主流,这些库是最高水平的实现,被大规模,广泛使用。

3) 这些库都是跨平台库,代码量不大,并且实用性又很高,功能单一,这就是c库的魅力所在。

4) 都是c语言实现,借助于ide的帮助,会很容易了解清楚整个流程。

3、libuv是什么?

libuv is a multi-platform support library with a focus on asynchronous I/O.

It was primarily developed for use by Node.js

由上面的介绍,我们可以知道:

1) 跨平台:windows linux unix都支持

2) 异步io:windows IOCP 、linux epoll、unix kqueue

3) 主要目的是用于nodejs,实际还有很多库或程序使用了libuv

例如目前风头正劲的跨平台.NetCore库(就是曾经大名鼎鼎的微软的asp.net)也是使用libuv作为核心

4) libuv不仅仅支持异步io操作,而且还具有一个强劲的线程池,用于支持多线程并行的cpu密集型操作。

这个才是我们重点要分析的模块

4、nodejs、google v8 javascript引擎和libuv之间的关系:

1) nodejs主要由google v8 javascript引擎和libuv组成

2) v8引擎绑定libuv实现的api,因此,既能使用ecma js标准语言来执行js代码,又能通过js调用libuv相关接口。

3) 由此可见,libuv本身是独立的c语言库,既可以直接使用c/c++来调用,也可以被绑定到c#(.NetCore)或者其他任何语言,例如java ,lua......

c/c++实现的库最大的好处就是能被各种其他编程语言所绑定和调用。

因为其他各种编程语言基本都是用c/c++来实现的,都留有接口与c/c++互调。

借用朴灵 深入浅出nodejs中的两张图来了解整个流程:

朴灵-深入浅出nodejs-架构图.png

朴灵-深入浅出nodejs-异步调用示意图.png

我们libuv源码分析以上图为指导,深入挖掘每个细节,验证其正确性,从而掌握整个libuv的精髓!

请将此图看上100遍,背出来,肯定有非常大帮助

nodejs就是数据通过v8引擎(主线程:数据输入)传递给Libuv进行处理(线程池:数据处理--根据数据类型不同,io数据由IOCP[windows]线程池处理,通用计算则由自己实现的线程池处理),libuv处理好后通知v8引擎我已经完成了,你来进行完成处理(主线程:完成回调,信息输出)。

其实从上面的叙述可以了解到以下几点:

1) v8 javascript引擎是单线程的,数据的输入,信息的输出(完成回调)都是在主线程中处理。这一点以后在源码分析中我们可以验证,通过vs强大的debug功能,我们可以很清晰的看到具体代码到底是运行在哪个线程中。

2) 但是数据处理模块(libuv)不是单线程的,它根据数据请求类型是否是io请求(socket,文件读写或管道等)还是work请求(非io请求)。不同的请求使用不同的处理策略。例如io请求,在windows下用IOCP,在linux下用epool。而work请求,windows和linux下都是使用统一的,自己实现的线程池。而我们的源码分析就是要证明上面的描述。

下一篇: 征服libuv之进展篇

.

你可能感兴趣的:(libuv访问mysql)