2013年8月

Nginx源码分析模块加载

转载请注明出处:http://www.firefoxbug.com/?p=2030

前文说了Nginx里万物皆模块,今天描述下模块的加载,因为模块的加载是一个递归的过程,所以比较难以理解。

模块类型


Nginx官方定义了6种核心模块,定义宏声明是NGX_CORE_MODULE,分别是ngx_core_module,ngx_http_module,ngx_events_module,ngx_mail_module,ngx_errlog_module,ngx_openssl_module。这6种核心模块又可以定义自己全新的模块,比如ngx_events_module重新定义events类型为NGX_EVENT_MODULE,ngx_http_module定义http模块类型NGX_HTTP_MODULE。在上文叙述的ngx_command_s第二个字段就是指定这些模块类型。

- 阅读剩余部分 -

Nginx源码分析模块化

断断续续读了近半个多月Nginx的源码,感觉还是比较吃力,因为Nginx模块化的设计带来的是复杂的结构体以及回调函数,逻辑比较复杂。到现在也不知道改怎么写好Nginx源码分析这类博客,但是只能硬着头皮去写,希望写的过程中能出现各种疑问从而解决。目前还没完整地读完源码,按照Nginx执行顺序写还力不从心,所以先从如何编写三方模块开始。

在之前一篇文章写了一个Nginx删除域名Cache的三方模块 http://www.firefoxbug.com/?p=1985,Nginx源码分析就从这个模块进行分析。至于什么是模块?我们从Nginx的配置文件出发来解释。

- 阅读剩余部分 -

Nginx动态加载模块

参考 http://tengine.taobao.org/document/dso.html

Tengine支持了动态加载模块,个人感觉这使得Nginx这个优秀的设计更加完美,在开发三方模块的时候大大提高了效率。下面举例子如何加载一个三方的模块,加载前面的站点cache一键清除模块(http://www.firefoxbug.com/?p=1985)。

/usr/local/nginx/sbin/dso_tool模块已经把编译成动态库的参数都写好了,只需要调用这个工具就行,参数是源码路径,包含要configure文件。

/usr/local/nginx/sbin/dso_tool -a=/home/nginx_move_domain_cache
或者
/usr/local/nginx/sbin/dso_tool --add-module=/home/node/Tengine/nginx_move_domain_cache

这样会自动生成 ngx_http__module.so 动态库并且dso_tool工具会将其copy到/usr/local/nginx/modules,下面就是配置Nginx。
events {
        use epoll;
        worker_connections  51200;
}

dso {
        load ngx_http_move_domain_cache_module.so;
}

http {
      ....
}

这样就能动态的加载 .so 模块,dso也是一个main级的配置。

Nginx添加访客地理位置到日志(GeoIP模块)

之前项目里用Nginx吐出access日志,然后用awstats来统计分析,结果对于访客地理位置比较头痛,于是自己写了几个程序查找(纯真库和GeoIP查找的方法不一样),今天看Nginx源码时候发现了可以利用--with-http_geoip_module这个模块,然后指定变量到日志。具体会有瓶颈,下面看怎么实现。

GeoIP库安装

- 阅读剩余部分 -

LVS概述

refer:http://snmlab.cs.nchu.edu.tw/CloudLab/CTSP/Lab7.html

今早X哥告诉我说他需要传10G/S的数据,我顿时就瞎了,他叫我给出下LVS的描述,我总结了下。

NAT


网络环境:LVS调度器两个网卡,一个公网IP,一个内网IP,限制于一个LAN里面。
原理:数据包到最前面的调度器(公网IP),转发到内网的机器群(内网IP),内部服务器相应完成后转发回调度器,调度器回到客户端。
总结:数据包都流经四层,调度器会是瓶颈,进出流量都经过调度器。

- 阅读剩余部分 -

Nginx一键清除域名下Cache

装载请注明出处:http://www.firefoxbug.com/?p=1985
在前面一篇文章 http://www.firefoxbug.com/?p=1861 已经介绍如何把站点缓存分域名存放。相比之前的purge一个个URL刷新,按照域名存放对于站点Cache一键刷新是很方便的。本文会介绍如何通过开发一个Nginx三方模块,一键刷新某个域名站点下缓存。 注意:在使用下面模块之前必须根据前文,站点Cache已经按照目录存储,目录在 /home/cache/下。比如 www.firefoxbug.net 的 Cache 是 /home/cache/www.firefoxbug.net/ ,通过模块能一键清除此目录cache。

- 阅读剩余部分 -

Player

[code]
[firefoxbug@firefoxbug ~]$ history | awk '{CMD[$2]++;count++;} END {for (a in CMD) print CMD[ a ]" " CMD[ a ]/count*100 "% "a}' | grep -v "./" | column -c3 -s " " -t | sort -nr | nl | head -n10 | cowsay
[/code]

test

OpenCDN2.0安装

部署说明

为网站加速,建立私有的CDN节点群,每部署一个CDN节点只需5分钟,无节点数量上限!参考 http://ocdn.me/ 安装需求 OpenCDN的Beta版目前在CentOS5.x - CentOS6.x 下测试通过。内存大小:不低于512M内存。安装前确保主机的80端口不被占用。 注意事项
  • OpenCDN2.0版目前提供了CDN集中管控中心,无需再独立部署管控端,只需部署多个CDN节点,从集中管控中心添加节点即可。
  • 如果节点机房所在地80端口因白名单等原因无法直接通信,请确保节点的 9242 端口放开(IPtables等防火墙),用以CDN管控端的通信。

- 阅读剩余部分 -

crontable shell 脚本

对于要添加单独一项的crontable,可以使用

echo “*/1 * * * *  /home/test.sh” | crontab -

但是之前要是已经有crontab的job就会覆盖了,所以要继续添加一项可以采用下面的方法。

crontab -l > mycron
echo "*/1 * * * *  /home/test.sh"
crontab mycron
rm mycron

Linux下I/O模型介绍

阻塞I/O


阻塞 I/O 模型是最原始的模型,进程一旦执行某个函数调用,进程就进入休眠状态(Sleeping)。比如平时FIFO管道的 read,还有基于TCP的流socket的 read 调用,进程一旦进行系统函数的调用,会从用户态切入内核态,内核会进行系统调用 read ,这时候如果对应的流(管道,socket都算)还没准备写入数据,那么 read 函数就会阻塞,从而导致进程挂起。直到数据来了,内核才会把数据拷贝从内核的缓冲区到进程用户的缓冲区。这时候 read 函数才能返回,进程才能向下走,继续下面的处理。整个过程是串行的,必须一步一步来。

- 阅读剩余部分 -

Python socket tcp

Server

#!/usr/bin/python

'''
	tcp socket server
'''

import sys
import socket

HOST = ''  
PORT = 9243
DATA_BUFFER = 4096

# create a TCP socket
try :
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
	print 'Socket created'
except socket.error, msg :
	print 'Failed to create socket. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
	sys.exit()

# Bind socket to local host and port
try:
	s.bind((HOST, PORT))
except socket.error , msg:
	print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
	sys.exit()

s.listen(5)			# allow 5 simultaneous

while True:
	# wait for next client to connect
	connection, address = s.accept()		# connection is a new socket
	while True:
		data = connection.recv(DATA_BUFFER) # receive up to 1K bytes
		if data:
			print data
		else:
			break
	connection.close()						# close socket

Client


#!/usr/bin/python

'''
	tcp socket client
'''

import socket  
  
address = ('223.4.238.138', 9243) 
# create a TCP socket
try :
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
	print 'Socket created'
except socket.error, msg :
	print 'Failed to create socket. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
	sys.exit()	

# create a TCP socket
try :
	s.connect(address)
	print 'Connect successfully'
except socket.error, msg :
	print 'Failed to Connect . Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
	sys.exit()

s.send('hello world')  

s.close()  

如何评价CDN加速服务商的好坏

针对CDN加速是否对SEO有影响,百度的说法是:

只要对用户友好的,只要对用户有益的。百度都欢迎。都不影响收录和排名。而且有好处。

但是技术上是否真的严格做到这一点。不知道。

所以,不用管什么cdn,做好用户体验才是王道。seo也只是一个部分而已。

因为CDN是基于缓存的,所以在使用CDN之后,有部分用户在访问网站时,实际上是得到了缓存,而没有真正去网站服务器上读取文件,因此会造成IP的下降。CDN对SEO的影响,一个关键应该是网站重复内容上面。

第一,CDN对SEO没有影响;

第二,Alexa的流量不代表真实的流量。

对页面访问量不会有坏的影响,你说的访问量大幅下降,如果和CDN直接相关的话,可能是你统计方式的问题,是不是你只统计了你们服务器的请求页面数。

首先,咋们要弄清楚的是CDN与爬虫抓取的原理,为什么会这样说呢?楼主的问题是CDN对SEO是否有影响,部分用户认为影响肯定有的。

第一:爬虫为什么只抓取网站的一级页面?2级、3级页面抓取速度慢,甚至不抓取。

第二:网站用了CDN与没有用CDN的对比,页面一级内容的抓取速度,是否加快了?

第三:SEO营销,最为注重的就是内容被爬虫快速抓取,刚好CDN能够解决你的1级、2级等页面的内容生成速度,以便被爬虫抓取,这只是一小部分而已。

1、使网站访问速度变快

这个是显而易见的。使用了CDN之后,网站的打开速度都很快。在百度和谷歌都将网页打开速度作为SEO的因素之一的情况下对于网页的收录和关键词的排名都是有利的。

2、收录有问题

当然这个方面是猜测,我也觉得CDN对于百度的收录也是存在一些问题的。特别是快照方面的情况。以下是这个方面的截图:原因探究:

1、回源机制

因为CDN服务器定期要发送请求同步更新源服务器上的文件内容。如果源数据服务器不给力,或者全国的点都选择在全部更新请求,这个可能会造成百度的蜘蛛在访问时没有看到页面,超时之后蜘蛛离开,按照规定进行处理时,呈献给客户网页也就是我们之前看到样子了。

Python open模式

open(file_name,mode)

w 以写方式打开,
a 以追加模式打开 (从 EOF 开始, 必要时创建新文件)
r+ 以读写模式打开
w+ 以读写模式打开 (参见 w )
a+ 以读写模式打开 (参见 a )
rb 以二进制读模式打开
wb 以二进制写模式打开 (参见 w )
ab 以二进制追加模式打开 (参见 a )
rb+ 以二进制读写模式打开 (参见 r+ )
wb+ 以二进制读写模式打开 (参见 w+ )
ab+ 以二进制读写模式打开 (参见 a+ )

注意:

1、使用'w',文件若存在,首先要清空,然后(重新)创建,
2、使用'a'模式 ,把所有要写入文件的数据都追加到文件的末尾,即使你使用了seek()指向文件的其他地方,如果文件不存在,将自动被创建。

Python 发送HEAD包

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import urllib2
import socket

def send(url):
	request = urllib2.Request(url,)
	try:
		request.get_method = lambda: 'HEAD'
		response = urllib2.urlopen(request)
		msg = response.msg
		print "message : %s"%msg
		headers = response.headers
		print "\n\n%s"%headers
		data = response.read()
		print "data\n%s"%data
	except urllib2.HTTPError,e:
		code = e.code
		print code
	except Exception,e:
		print e

socket.setdefaulttimeout(2)
send("http://74.91.23.207/")

Head方法要求响应与GET请求一样,但是没有响应体(response body)。如果我们只对关于网页或资源的
信息感兴趣,而不想检索资源本身的全部内容,可以使用HEAD命令。HEAD的使用方法与GET相同,只是不返
回Web页的正文内容。