tcp拥塞算法vegas分析

tcp的vegas算法是基于delay的一个拥塞控制算法,所谓基于delay也就是说窗口的变化只和RTT的变化相关。而传统的基于丢包的算法是窗口的变化和丢包相关.

先来看原理,paper地址在这里(94年提出来的),基本上linux的实现就是按照paper来实现的,注意Vegas它是第一个基于delay的拥塞算法.

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.100.9587&rep=rep1&type=pdf

它的主要思想是估计一段时间能够发送的数据量,然后和最终发送的数据量比较。如果预测要发送的数据没有被发送,那么就会被认为可能出现拥塞状况,如果这个状态持久,那么就减慢发送速度,并且这个算法不仅作用于拥塞避免状态,而且还作用于slow start状态。

不过vegas的缺点也是很明显.那就是他会被欺骗,也就是说本身这个正向的延迟就是比它期待的高,比如在tcp中,有可能正向反向做的不是相同的路径,那么当反向有拥塞的时候,就有问题了。也就是数据包ack返回给发送端的就是延迟的。此时就会导致Vegas降低拥塞窗口。这个问题就是基于延迟的拥塞算法的一个陷阱。不过在linux下vegas算法被打开,只有是正常状态才会被打开,而只要遇到异常(丢包/快重传..)就会使用经典的newreno算法.

并且如果连接都是Vegas算法,那么这些连接就是公平的,而如果有些是,有些不是,那么就不是公平的了,因此经典的tcp发送者是会尝试填满网络中的队列,而Vegas是尝试着保持队列为空。因此最终就会导致使用经典tcp拥塞算法的,发送的数据包越来越多,而Vegas的就会越来越慢。

阅读全文

tcp中RTO的计算以及linux下的实现

计算RTT以及RTO的代码比较简单,我们先来看原理,首先相关的rfc有两篇分别是rfc793以及rfc6298,而相关的paper有一篇,那就是Van Jacobson和Michael J. Karels的 Congestion Avoidance and Control这篇paper,这篇1988年的paper中描述的RTT计算方法,就是我们当前所使用的计算方法,可能有的操作系统有一点修改,不过基本的东西都一样。

首先RTT是什么,RTT简单来说,就是我发送一个数据包,然后对端回一个ack,那么当我接到ack之后,就能计算出从我发送出包到接到过了多久,这个时间就是RTT。RTT的计算是很简单的,就是一个时间差。

而RTO呢,RTO也就是tcp在发送一个数据包之后,会启动一个重传定时器,而RTO就是这个定时器的重传时间,那么这个时候,就有问题了,由于RTO是指的这次发送当前数据包所预估超时时间,那么RTO就需要一个很好的统计方法,来更好的预测这次的超时时间。

我们所能想到的最简单的方法,那就是取平均数,比如第一次RTT是500毫秒,第二次是800毫秒,那么第三次发送的时候,RTO就应该是650毫秒。其实经典的RTO计算方法和取平均有点类似,只不过因子不太一样,取平均的话,也就是老的RTO和新的RTT都是占50%的权重,而在经典的RTO计算中就有些变化了。

阅读全文

nginx least_conn 模块源码剖析

nginx在1.3.1添加了一个新模块 least_conn,也就是我们常说的最少连接负载均衡算法,简单来说就是每次选择的都是当前最少连接的一个server(这个最少连接不是全局的,是每个进程都有自己的一个统计列表)。

在看最少连接模块之前需要对round robin模块有一定的了解,这里我就不对round robin模块进行分析了,想要看这块代码,可以去我们组 卫岳的blog的这篇文章

http://blog.sina.com.cn/s/blog_7303a1dc01014i0j.html

ok,接下来就来看这个模块,首先来看如何打开least_conn模块:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  
static ngx_command_t ngx_http_upstream_least_conn_commands[] = {

{ ngx_string("least_conn"),

NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS,

ngx_http_upstream_least_conn,

0,

0,

NULL },

ngx_null_command

};

阅读全文

打开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]

阅读全文