在网上看到一篇关于Nginx和Node.js调优的好文,记录之
Apache Nutch and Solr 初试
简介
Apache Nutch 是一个用JAVA语言编写的开源web爬虫项目。通过使用它,我们能够以一种自动化的方式找到web页面上的超链接, 减少了大量的维护工作,例如检查无用的链接或者创建一个所有访问过搜索页面的副本。讲到这里Apache Solr出现, Solr是一个开源的全文检索框架,通过solr我们能搜索Nutch访问过的页面。幸运的是,整合Nutch和Solr是十分简单的,例如下面的讲解。
Apache Nutch 支持Solr拆箱即用,使得Nutch 和solr的整合非常简单。同时也去除了遗留的依赖问题: 不必在Apchce tomcat上运行老版本的Nutch web应用程序,也不必基于Lucene进行搜索
Nutch安装测试
nutch 和 solr 都需要首先安装apache hadoop并设置JAVA_HOME, HADOOP_INSTALL并将其添加进环境变量中 下载nutchDownload的二进制版本,这里面用的是1.6版本 解压到某文件夹内后进入
修改nutch-site.xml
1 2 3 4 |
|
创建种子文件
1 2 3 |
|
修改conf/regex-urlfilter.txt 将
1 2 |
|
替换为
1
|
|
创建抓取文件夹
1 2 |
|
运行抓取
1
|
|
Solr安装测试
问题
org.apache.hadoop.mapred.InvalidInputException: Input path does not exist
由于抓取文件夹访问异常造成,需要执行创建mycrawl并赋予777权限
参考
Using Cppcheck
简介
cppcheck 是一个静态代码检查工具,支持c, c++ 代码;作为编译器的一种补充检查,cppcheck对产品的源代码执行严格的逻辑检查。 执行的检查包括
1. 自动变量检查 2. 数组的边界检查 3. class类检查 4. 过期的函数,废弃函数调用检查 5. 异常内存使用,释放检查 6. 内存泄漏检查,主要是通过内存引用指针 7. 操作系统资源释放检查,中断,文件描述符等 8. 异常STL 函数使用检查 9. 代码格式错误,以及性能因素检查
安装和使用
1
|
|
使用
1
|
|
Google Python Style
概述
对于Python来说,有其自己的一套语法规范,同时由于python在google里的大量应用,类似于google的c++规范。也有一个类似的python style 下面是一些摘要
摘要
工具
pychecker
1
|
|
使用的话直接运行
1
|
|
只检测文件自身语法,添加only选项
1
|
|
内容
- 使用模块的全路径名来导入每个模块
- 模块或包应该定义自己的特定域的异常基类, 这个基类应该从内建的Exception类继承
- 避免全局变量
- 鼓励使用嵌套/本地/内部类或函数
- lambda适用于单行函数
- 访问和设置数据成员时, 你通常会使用简单, 轻量级的访问和设置函数. 建议用属性来代替它们
- 永远不要用==或者!=来比较单件, 比如None. 使用is或者is not.
- 永远不要用==将一个布尔量与false相比较
- 对于序列(字符串, 列表, 元组), 要注意空序列是false
- 注意‘0’(字符串)会被当做true
- 不要依赖内建类型的原子性
- 避免使用过于技巧性的特性
参考
Ubuntu Sudo 无密码
使得sudo无需密码
需要修改/etc/sudoer 尽量使用
1
|
|
进行修改,保证不会因为出错无法使用sudo
1
|
|
直接修改/etc/sudoer出错处理
进入recovery模式的root账户,执行
1 2 |
|
去除只读模式后,修改/etc/sudoer文件 最后
1
|
|
Keepalived使用
概述
项目中使用redis和自己编写的模块,需要用keepalived进行管理。下面的是相关资料和步骤。
安装
ppa安装
在Ubuntu12.04上进行安装
1 2 |
|
配置
源码安装
拷贝/usr/loacl/etc/rc.d/keepalived进/etc/init.d 修改/etc/init.d/keepalived三处
1 2 |
|
1 2 |
|
1 2 3 4 5 6 7 8 |
|
创建目录
1
|
|
安装daemon
1
|
|
ppa安装
1
|
|
配置
日志配置
查看日志需要安装syslog
1
|
|
修改日志显示配置
1
|
|
在/etc/syslog.conf后添加
1 2 |
|
重启sysklogd
修改/etc/init.d/keepalived
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
重启keepalived
测试
利用apache2进行测试,首先安装
1
|
|
其配置文件在/etc/apache2中,网页文件为/var/www/index.html 根据不同的server修改index.html中的内容
master
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
|
slave
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
|
脚本文件在/etc/keepalived中
1 2 3 4 5 6 7 8 9 10 11 |
|
分别启动master和slave,利用下面命令查看当前服务的server
1
|
|
然后关闭master上面的apache2,仍然用命令查询状态发现已经转移到slave上
配置文件
对于项目中的使用来说,需要同时监测redis和自己写的模块(asio_manager_sh)其配置脚本如下
通用配置
redis需要修改的配置
1 2 |
|
通用脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
启动redis脚本
1 2 3 4 5 |
|
启动asio_manager_sh
1 2 3 4 5 |
|
启动keepalived脚本
1 2 3 |
|
停止所有脚本
1 2 3 4 5 |
|
检测manager脚本
1 2 3 4 5 6 7 |
|
检测redis脚本
1 2 3 4 5 6 7 |
|
检测redis和manager脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
停止keepalived时运行的脚本
1 2 3 4 5 6 7 |
|
链接出错脚本
1 2 3 4 5 6 7 |
|
master上脚本
成为master脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
成为backup脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
keepalived配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
|
backup上脚本
成为master
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
成为backup
1 2 3 4 5 6 7 8 9 10 11 |
|
keepalived配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
|
注:
需要首先启动master,然后等待第一次both_check成功后再启动backup
先启动redis再启动keepalived,必要的话可以用chkconfig进行启动配置
问题
参考
OpenStack Install on Ubuntu
概述
对于OpenStack的学习笔记之一,简单记录在Ubuntu 12.04上面安装OpenStack并进行简单 测试。基本步骤按照参考1来进行
步骤
安装依赖
ntp服务
1
|
|
将下面的内容添加进/etc/ntp.conf
1 2 3 |
|
重启ntp服务
1
|
|
tgt
nova-volume需要tgt支持,安装它
1
|
|
然后启动服务
1
|
|
openiscsi-client
nova-compute需要
1
|
|
network
需要配置网络,如果没有使用NetworkManager,编辑/etc/network/interfaces,例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
bridge-utils
1 2 |
|
AMQP
1
|
|
kvm
1
|
|
配置MySQL
1
|
|
修改/etc/mysql/my.cnf
1
|
|
重启mysql
1
|
|
配置数据库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
安装配置Keystone
1
|
|
编辑/etc/keystone/keystone.conf
1 2 3 |
|
重启并同步数据库
1 2 |
|
下载keystone_data.sh_.txt和endpoints.sh_.txt 修改keystone_data.sh_.txt
1 2 |
|
运行
1
|
|
安装配置Glance
1
|
|
编辑/ect/glance/glance-api-paste.ini和/etc/glance/glance-registry-paste.ini
1 2 3 |
|
编辑/ect/glance/glance-registry.conf
1
|
|
在/etc/glance/glance-registry.conf和/etc/glance/glance-api.conf末尾添加
1 2 |
|
运行
1 2 |
|
重启
1
|
|
下载img
1
|
|
安装配置Nova
第一个VM
Dashboard
参考
Install Hadoop on Ubuntu
概述
Hadoop 由 Apache Software Foundation 公司于 2005 年秋天作为 Lucene 的子项目 Nutch 的一部分正式引入。它受到最先由 Google Lab 开发的 MapReduce 和 Google File System 的启发。2006 年 3 月份,MapReduce 和 Nutch Distributed File System (NDFS) 分别被纳入称为 Hadoop 的项目中。 Hadoop 是最受欢迎的在 Internet 上对搜索关键字进行内容分类的工具,但它也可以解决许多要求极大伸缩性的问题
安装
软件
软件版本分别为
- java: jdk-7u9-linux-x64
- hadooop: hadoop-1.1.1.tar.gz
- eclipse: eclipse-java-juno-SR1-linux-gtk-x86_64
步骤
JAVA
解压jdk-7u9-linux-x64.tar.gz到/usr/lib/jvm中
运行
1 2 3 4 5 6 7 |
|
选择对应的版本
类似配置javac, javaws
完成后判断java以及javac版本
1 2 |
|
在/etc/profile中添加
1 2 3 4 |
|
完成后需要重启
Hadoop
创建用户组以及用户hadoop
1 2 |
|
将hadoop用户组添加进sudoer中,在/etc/sudoers中添加如下内容
1
|
|
修改不用密码执行sudo
1
|
|
修改下面的项
1
|
|
重启后以hadoop用户登录
配置ssh
安装opensssh-server
1
|
|
配置密码
1 2 |
|
测试
1
|
|
可以不用密码登录
禁用ipv6 可能出现问题:在ubuntu上使用IPV6会有一个问题,就是不同的网络环境配置hadoop会导致hadoop与IPV6地址绑定
在/etc/sysctl.conf中添加
1 2 3 4 |
|
完成后重启
测试是否有效
1
|
|
0表示没有成功,1表示设置成功
配置hadoop
以single node为例,hadoop版本为1.1.1
解压到某个文件夹内,比如/opt 在~/.bashrc中添加
1 2 |
|
设置conf/hadoop-env.sh,添加
1
|
|
根据不同的启动方式配置相关文件,一共有三种启动方式:本地模式,伪分布式,完全分布式
格式化hdfs
1
|
|
查看日志
Eclipse
参考
C10k 相关
简介
网络服务在处理数以万计的客户端连接时,往往出现效率低下甚至完全瘫痪,这被称为 C10K问题。随着互联网的迅速发展,越来越多的网络服务开始面临C10K问题.这个问题在2001年被c10k提出
经典的多线程模式和select模式都不再适用。 应当抛弃它们,采用epoll/kqueue/dev_poll来捕获I/O事件C10K问题, c10k翻译
c10k问题
C10K问题的最大特点是:设计不够良好的程序,其性能和连接数及机器性能的关系往往 是非线性的。举个例子:如果没有考虑过C10K问题,一个经典的基于select的程序能在 旧服务器上很好处理1000并发的吞吐量,它在2倍性能新服务器上往往处理不了并发 2000的吞吐量
常用框架模式
Serve many clients with each thread, and use nonblocking I/O and level-triggered readiness notification
把网络句柄设置为非阻塞模型,然后使用select()或poll()来告知哪个句柄已有数据在等待 处理。 此模型是最传统的,在此模型下,由内核告知你某个文件描述符是否准备好,是否已经完成你的任务
Serve many clients with each thread, and use nonblocking I/O and readiness change notification
Readiness change notification(或边缘触发就绪通知)的意思就是当你给内核一个文件描述 符,一段时间后, 如果该文件描述符从没有就绪到已经准备就绪,那么内核就会发出通知,告知 该文件描述符已经就绪, 并且不会再对该描述符发出类似的就绪通知直到你在描述符上进行一些 操作使得该描述符不再就绪 (如直到在send,recv或者accept等调用上遇到EWOULDBLOCK错误,或 者发送/接收了少于需要的字节数)。
当使用Readiness change notification时,必须准备好处理乱真事件,因为最常见的实现是只 要接收到任何数据包都发出就绪信号, 而不管文件描述符是否准备就绪
Serve many clients with each server thread, and use asynchronous I/O
IO使用的是边缘触发的完成时通知,例如,当一个操作完成时信号就被加入队列
Serve one client with each server thread
让read()和write()阻塞. 这样不好的地方在于需要为每个客户端使用一个完整的栈,从而比较浪费内存。 许多操作系统仍在处理数百个线程时存在一定的问题
Build the server code into the kernel
Novell和Microsoft都宣称已经在不同时期完成了该工作,至少NFS的实现完成了该工作。 khttpd在Linux下为静态web页面完成了该工作, Ingo Molnar完成了”TUX” (Threaded linUX webserver) ,这是一个Linux下的快速的可扩展的内核空间的HTTP服务器
在Linux内核的邮件列表上讨论了该方法的好处和缺点,多数人认为不应该把web服务器放进内核中, 相 反内核加入最小的钩子hooks来提高web服务器的性能,这样对其它形式的服务器就有益
影响服务器性能方面
高性能服务器架构(High-Performance Server Architecture)里面论述了影响服务器架构性能的若干方面
数据拷贝(Data Copies)
有一种可以避免数据拷贝的方法是使用buffer的描述符(或者buffer chains的描述符)来取代直接使用buffer指针, 每个buffer描述符应该由以下元素组成: - 一个指向buffer的指针和整个buffer的长度 - 一个指向buffer中真实数据的指针和真实数据的长度,或者长度的偏移 - 以双向链表的形式提供指向其它buffer的指针 - 一个引用计数
我不建议在任何情况下都使用这种技术,因为当你想在链上搜索你想要的一个块时,就不得不遍历一遍描述符链,这甚至比数据拷贝更糟糕。 最适用这种技术地方是在程序中大的数据块上,这些大数据块应该按照上面所说的那样独立的分配描述符,以避免发生拷贝, 也能避免影响服务器其它部分的工作
关于数据拷贝最后要指出的是:在避免数据拷贝时不要走极端
上下文切换(Context Switches)
在我的经验里,比起数据拷贝,上下文切换是让高负载应用彻底完蛋的真正杀手。系统更多的时间都花费在线程切换上, 而不是花在真正做有用工作的线程上
引起环境切换的第一个原因往往是活跃线程数比CPU个数多。随着活跃线程数相对于CPU个数的增加,上下文切换的次数也在增加, 如果你够幸运,这种增长是线性的,但更常见是指数增长
一个有适量线程的程序首先要考虑的事情是规划出如何创建一个线程去管理多连接c10k
引起环境切换的第二个原因是把对请求的处理从一个线程转移到另一个线程
限制激活线程的数量:
根据cpu个数限制线程个数?
最简单同时也是最有效的方法之一是:用一个老式的带计数的信号量,每一个线程执行的时候就先持有信号量。如果信号量已经到了最大值,那 些处于监听模式的线程被唤醒的时候可能会有一次额外的环境切换,(监听线程被唤醒是因为有连接请求到来, 此时监听线程持有信号量时发现 信号量已满,所以即刻休眠), 接着它就会被阻塞在这个信号量上,一旦所有监听模式的线程都这样阻塞住了,那么它们就不会再竞争资源了, 直到其中一个线程释放信号量,这样环境切换对系统的影响就可以忽略不计
一旦处理请求的过程被分成两个阶段(监听和工作),那么更进一步,这些处理过程在将来被分成更多的阶段(更多的线程)
应该注意到在这种模式下,对阶段的排队是在一个线程内完成的,而不是经由两个线程中完成。这样避免不断把请求放在下一阶段的队列里,紧接着又从该队列取出这个请求来执行。这种经由很多活动队列和锁的阶段很没必要
内存分配(Memory Allocator)
- 使用预分配
- 使用一个内存释放分配的lookaside list(监视列表或者后备列表)
- 第三条建议与我们还没有讨论的锁有关系
锁竞争(Lock Contention)
高效率的锁是非常难规划的, 以至于我把它称作卡律布狄斯和斯库拉(参见附录)。一方面, 锁的简单化(粗粒度锁)会导致并行处理的串行化, 因而降低了并发的效率和系统可伸缩性; 另一方面, 锁的复杂化(细粒度锁)在空间占用上和操作时的时间消耗上都可能产生对性能的侵蚀。 偏向于粗粒度锁会有死锁发生,而偏向于细粒度锁则会产生竞争
首要的事情是为你程序中的锁形成一张图表,有两个轴
- 纵轴表示代码。如果你正在应用剔出了分支的阶段架构
- 水平轴表示数据集。在请求的每个阶段都应该有属于该阶段需要的数据集
最重要的规则:两个请求不应该产生竞争,除非它们在同一个阶段需要同样的数据集
你定义出了上面那个网格图,在你的系统中的每种类型的锁就都可以被标识出来了。 你的下一个目标是确保这些标识出来的锁尽可能在两个轴之间均匀的分布, 这部分工作是和具体应用相关的
- 如果你能对请求按顺序编号,或者能对请求进行哈希,或者能把请求和事物ID关联起来,那么根据这些编号或者ID就能对数据更好的进行分隔。
- 有时,基于数据集的资源最大化利用,把请求动态的分配给数据,相对于依据请求的固有属性来分配会更有优势。就好像现代CPU的多个整数运算单元知道把请求分离一样
- 确定每个阶段指定的数据集是不一样的是非常有用的,以便保证一个阶段争夺的数据在另外阶段不会争夺
其他方面
- 你的存储子系统在大数据读写和小数据读写,随即读写和顺序读写方面是如何进行?在预读和延迟写入方面做得怎样?
- 你使用的网络协议效率如何?是否可以通过修改参数改善性能?是否有类似于TCP_CORK, MSG_PUSH,Nagle-toggling算法的手段来避免小消息产生?
- 你的系统是否支持Scatter-Gather I/O(例如readv/writev)? 使用这些能够改善性能,也能避免使用缓冲链(见第一节数据拷贝的相关叙述)带来的麻烦
- 你的系统的页大小是多少?高速缓存大小是多少?向这些大小边界进行对起是否有用?系统调用和上下文切换花的代价是多少?
- 你是否知道锁原语的饥饿现象?你的事件机制有没有”惊群”问题?你的唤醒/睡眠机制是否有这样糟糕的行为: 当X唤醒了Y, 环境立刻切换到了Y,但是X还有没完成的工作?
c500k c1000k
从 C10K 到 C500K讨论了 Urban Airship c500k的实现,基于Java + Pure NIO.参考文档A Million-user Comet Application with Mochiweb, Part 1 另外涉及内核调优的方法Linux Kernel Tuning for C500k
Select和Poll在连接数增加时,性能急剧下降的原因
- 首先操作系统面对每次的select/poll操作,都需要重新建立一个当前线程的关心事件列表,并把线程挂在这个复杂的等待队列上,这是相当耗时的
- 其次,应用软件在select/poll返回后也需要对传入的句柄列表做一次扫描来dispatch,这也是很耗时的。这两件事都是和并发数相关,而I/O事件的密度也和并发数相关,导致CPU占用率和并发数近似成O(n2)
Linux 2.6.35 Kernel Google捐赠了的两项新特性可以在系统的多个CPU之间分配网络处理负载,改进网络处理的性能
C1000K高性能服务器构建技术讨论了淘宝构建高性能服务器的经验
参考
Nginx 参考
简介
Nginx是当前最流行的HTTP Server之一,根据W3Techs的统计,目前世界排名 (根据Alexa)前100万的网站中,Nginx的占有率为6.8%。与Apache相比, Nginx在高并发情况下具有巨大的性能优势。 Nginx属于典型的微内核设计,其内核非常简洁和优雅,同时具有非常高的可扩展性。 Nginx最初仅仅主要被用于做反向代理,后来随着HTTP核心的成熟和各种HTTP扩展模块的丰富, Nginx越来越多被用来取代Apache而单独承担HTTP Server的责任,例如目前淘宝内各个部门正越来越多使用Nginx取代Apache, 据笔者了解,在腾讯和新浪等公司也存在类似情况
源码
模块化
- Nginx模块开发入门
- Emiller’s Guide To Nginx Module Development
- Emiller’s Advanced Topics In Nginx Module Development
- subrequest blog
- 开发nginx模块之Hello World篇
- Nginx开发从入门到精通
- lua with nginx
- Nginx+Lua+Redis整合实现高性能API接口