打开tcp_tw_recycle引起的一个问题

今天普空说了一个问题就是如果设置了tcp_tw_recycle ,那么如果客户端是NAT出来的,那么就可能会出现连接被直接rst的情况。然后我google了下,在内核列表也有人说了这个问题 https://lkml.org/lkml/2008/11/15/67

The big problem is that both are incompatible with NAT. So if you

ever talk to any NATed clients don’t use it.

阅读全文

一个out of socket memory的问题

今天同事遇到一个问题,就是server(read hat 5, kernel 2.6.18)的dmesg打出了下面两个信息

TCP: too many of orphaned sockets

Out of socket memory

一般我们看到这个信息,第一反应肯定是需要调节tcp_mem(/proc/sys/net/ipv4)了,可是根据当时的内存使用情况,使用的内存并没有超过 tcp_mem。然后我先去看了最新的内核代码,3.4.4,其中涉及到socket 内存报警在这里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  
bool tcp_check_oom(struct sock *sk, int shift)

{

bool too_many_orphans, out_of_socket_memory;

too_many_orphans = tcp_too_many_orphans(sk, shift);

out_of_socket_memory = tcp_out_of_memory(sk);

if (too_many_orphans && net_ratelimit())

pr_info("too many orphaned sockets\n");

if (out_of_socket_memory && net_ratelimit())

pr_info("out of memory — consider tuning tcp_mem\n");

return too_many_orphans || out_of_socket_memory;

}

上面的代码很简单,就是如果孤儿socket太多,则打印警告,然后如果socket memory超过限制,也打印出警告。

阅读全文

intel万兆网卡驱动简要分析

这里分析的驱动代码是给予linux kernel 3.4.4

对应的文件在drivers/net/ethernet/intel 目录下,这个分析不涉及到很细节的地方,主要目的是理解下数据在协议栈和驱动之间是如何交互的。

首先我们知道网卡都是pci设备,因此这里每个网卡驱动其实就是一个pci驱动。并且intel这里是把好几个万兆网卡(82599/82598/x540)的驱动做在一起的。

首先我们来看对应的pci_driver的结构体,这里每个pci驱动都是一个pci_driver的结构体,而这里是多个万兆网卡共用这个结构体ixgbe_driver.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  
static struct pci_driver ixgbe_driver = {

.name = ixgbe_driver_name,

.id_table = ixgbe_pci_tbl,

.probe = ixgbe_probe,

.remove = __devexit_p(ixgbe_remove),

#ifdef CONFIG_PM

.suspend = ixgbe_suspend,

.resume = ixgbe_resume,

#endif

.shutdown = ixgbe_shutdown,

.err_handler = &ixgbe_err_handler

};

阅读全文

mochiweb源码分析(二)

这次主要来看mochiweb如何处理http协议以及如何将外部模块加载到mochiweb框架中。

首先在上一篇的分析最后,我们知道当accept句柄之后,mochiweb最终会调用call_loop方法,那么我们就从call_loop开始

[erlang]

call_loop({M, F}, Socket) ->

M:F(Socket);

call_loop({M, F, [A1]}, Socket) ->

M:F(Socket, A1);

call_loop({M, F, A}, Socket) ->

erlang:apply(M, F, [Socket | A]);

call_loop(Loop, Socket) ->

Loop(Socket).

[/erlang]

阅读全文

mochiweb源码分析(一)

这篇主要分析下mochiweb的整体结构。

我这里看的代码是github上的最新代码( https://github.com/mochi/mochiweb )。

由于mochiweb是一个框架,因此我们就从他自带的简单例子入手,来看他是如何工作的。我们就从keepalive.erl开始。

首先来看这个模块的start函数,也就是它的启动函数:

[erlang]

-define(LOOP, {?MODULE, loop}).

start(Options = [{port, _Port}]) ->

mochiweb_http:start([{name, ?MODULE}, {loop, ?LOOP} | Options]).

[/erlang]

可以看到启动函数非常简单,那就是直接调用mochiweb_http模块的start函数。那么我们整个分析流程,就从这个模块的start函数开始。这里要注意,我们可以看到是将当前回调模块的loop函数传递给了mochiweb_http,这就给后续调用回调,提供了接口。

[erlang]

%% @spec start(Options) -> ServerRet

%% Options = [option()]

%% Option = {name, atom()} | {ip, string() | tuple()} | {backlog, integer()}

%% | {nodelay, boolean()} | {acceptor_pool_size, integer()}

%% | {ssl, boolean()} | {profile_fun, undefined | (Props) -> ok}

%% | {link, false}

%% @doc Start a mochiweb server.

%% profile_fun is used to profile accept timing.

%% After each accept, if defined, profile_fun is called with a proplist of a subset of the mochiweb_socket_server state and timing information.

%% The proplist is as follows: [{name, Name}, {port, Port}, {active_sockets, ActiveSockets}, {timing, Timing}].

%% @end

start(Options) ->

mochiweb_socket_server:start(parse_options(Options)).

[/erlang]

阅读全文

Nginx配置文件解析详解

Nginx的配置解析相关的部分比较绕,比如为何要有4重指针,比如NGX_MAIN_CONF , loc_conf,NGX_DIRECT_CONF有什么区别呢?这些我前面的blog都有些涉及,这次主要是把配置这块完全拿出来然后来分析下。

首先来看配置解析时的数据结构,这里主要是ngx_conf_t,这个结构保存了解析配置文件所需要的一些域,这个是非常重要的一个数据结构,我们详细来看这个结构:

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
  
struct ngx_conf_s {

//当前解析到的命令名

char *name;

//当前命令的所有参数

ngx_array_t *args;

//使用的cycle

ngx_cycle_t *cycle;

//所使用的内存池

ngx_pool_t *pool;

//这个pool将会在配置解析完毕后释放。

ngx_pool_t *temp_pool;

//这个表示将要解析的配置文件

ngx_conf_file_t *conf_file;

//配置log

ngx_log_t *log;

//主要为了提供模块的层次化(后续会详细介绍)

void *ctx;

//模块类型

ngx_uint_t module_type;

//命令类型

ngx_uint_t cmd_type;

//模块自定义的handler

ngx_conf_handler_pt handler;

//自定义handler的conf

char *handler_conf;

};

阅读全文

hotwheels源码剖析

在霸爷的推荐下,看了hotwheels的代码,接下来我就来分析下hotwheels的代码(主要是server端代码),hotwheels是干吗的呢,介绍在这里:

https://github.com/tolbrino/hotwheels

Janus is a messaging server optimized to unicast over TCP to thousands of clients subscribed to topics of interest.

The ultimate goal is to maintain a latency of less than 2 seconds for 20 thousand clients on Amazon EC2 (small instance).

首先来看janus.app:

[erlang]

{application, janus,

[{description, “Janus”},

{vsn, “0.0.1”},

{id, “janus”},

{modules, [barrier,

bin,

bot,

client_proxy,

common,

flashbot,

histo,

janus,

janus_acceptor,

janus_admin,

janus_app,

janus_flash,

launcher,

mapper,

pubsub,

topman,

t,

transport,

util

]},

{registered, [janus_sup,

janus_topman_sup,

janus_proxy_mapper_sup,

janus_transport_sup,

janus_listener]},

{applications, [kernel,

stdlib,

mnesia,

inets

]},

{mod, {janus_app, []}},

{env, []}

]

}.

[/erlang]

阅读全文

nginx中cache的设计和实现(一)

Nginx的cache实现比较简单,没有使用内存,全部都是使用文件来对后端的response进行cache,因此nginx相比varnish以及squid之类的专门做cache的server,可能效果不会那么好。特别如果cache内容比较大的话。不过还有一种折衷的处理,那就是挂载一个内存盘,然后让nginx cache到这个盘。

我这里的看的代码是1.1.17.

首先来看Nginx中如何开启cache,http cache主要是应用在upstream中的,因此upstream对应的两个命令来启用cache,一个是xxx_cache_path(比如proxy_cache_path),它主要是用来创建管理cache的共享内存数据结构(红黑树和队列).一个是xxx_cache,它主要是使用前面创建的zone。

先来看第一个命令,xxx_cache_path,它会调用ngx_http_file_cache_set_slot函数,在看这个函数之前,先来看ngx_http_file_cache_t这个数据结构,它主要用来管理所有的cache文件,它本身不保存cache,只是保存管理cache的数据结构。每一个xxx_cache_path都会创建一个ngx_http_file_cache_t.

阅读全文

c reference manual读书笔记(五)

这次主要是介绍一些c语言中的类型转换。

1 在c语言里面,除了位域之外所有的数据对象都是表示为一堆抽象的存储单元,每一个存储单元都是由很多位组成的,每位的值不是1就是0,并且每一个存储单元都必须有唯一的地址,并且他们的每一个的大小都是和char的大小一致。每个存储单元有多少位,c语言并没有要求,可是每个存储单元必须能够存储基本字符集的每一个字符。 在标准c中也称存储单元为byte。

2 c程序员一般来说不需要在意一些机器的对齐限制,因为编译器会做对齐操作,但是,c也给了程序员忽略对齐限制的能力,比如cast一个指针到另外的类型。不过这里要注意,假设你要将一个类型为S的指针转换成类型T的指针,此时如果S的对齐因子如果不小于T的对齐因子,那么这个转换就是安全的(也就是说此时你取T的值,是没问题的). 可是如果S的对齐因子如果小于T的对齐因子,此时会出现两种情况,第一种就是当使用转换后的指针时,直接出错。第二种就是硬件或者编译器来帮你找到一个合适的指针来使用这个地址。

3 c99中定义了指针类型uintptr_t和intptr_t这两个值并不是指针的大小,而是指针类型不会超过这两个值, 这里要注意,很多实现中函数指针和数据指针大小是不一样的。而NULL只是数据空指针。对象的值和对象类型的值是不一样的,因为会有一些padding,而这些padding是没有定义的,

阅读全文

nginx的upstream分享

今天给同事做的分享.

阅读全文