1、数据的接收:
// readv将读入的数据按上述同样顺序散布读到缓冲区中。readv总是先填满一个缓冲区,然后再填写下一个。readv返回读到的总字节数。如果遇到文件结尾,已无数据可读,则返回0。
n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts);
放到列表 中
iov = ngx_array_push(&vec);
2、发送大量数据的处理:
读取数据
if (iov == NULL) {
return NGX_CHAIN_ERROR;
}
设置套接口
// TCP_NODELAY选项禁止Nagle算法。
// Nagle算法通过将未确认的数据存入缓冲区直到蓄足一个包一起发送的方法,来减少主机发送的零碎小数据包的数目。
// 但对于某些应用来说,这种算法将降低系统性能。所以TCP_NODELAY可用来将此算法关闭。
// 应用程序编写者只有在确切了解它的效果并确实需要的情况下,才设置TCP_NODELAY选项,因为设置后对网络性能有明显的负面影响。
// TCP_NODELAY是唯一使用IPPROTO_TCP层的选项,其他所有选项都使用SOL_SOCKET层。
if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
(const void *) &tcp_nodelay, sizeof(int)) == -1)
{
err = ngx_errno;
发送数据
// sendfile()是作用于数据拷贝在两个文件描述符之间的操作函数.这个拷贝操作是内核中操作的,所以称为"零拷贝".sendfile函数比起read和write函数高效得多,因为read和write是要把数据拷贝到用户应用层操作.
//
// 参数说明:
// out_fd 是已经打开了,用于写操作(write)的文件描述符;
// in_fd 是已经打开了,用于读操作(read)的文件描述符;
// offset 偏移量;表示sendfile函数从in_fd中的哪一偏移量开始读取数据.如果是零表示从文件的开始读,否则从相应的便宜量读取.如果是循环读取的时候,下一次offset值应为sendfile函数返回值加上本次的offset的值.
// count是在两个描述符之间拷贝的字节数(bytes)
// sendfile()在两种情况下才体现优势,但我却没有环境测试:
//
// 1. 大并发量的文件服务器或HTTP服务器;
// 2. 内存资源紧张的嵌入式系统;
// 3.和setsockopt一起使用
// 为什么要用sendfile?
// 原因很简单,项目中有个需求是后端程序负责把源文件打包加密生成目标文件,然后程序读取目标文件返回给浏览器;这种做法有个致命的缺陷就是占用大量后端程序资源,如果遇到一些访客下载速度巨慢,就会造成大量资源被长期占用得不到释放,很快后端程序就会因为没有资源可用而无法正常提供服务。通常表现就是nginx报502错误!其次在nginx内部我还想实现“由nginx检查目标文件是否存在,如果存在的话就直接返回给浏览器而无需经过后端程序的处理”,这样一来后端程序只是负责生成目标文件,一单目标文件被生成,基本上就不再提供服务,而nginx则提供全静态的文件浏览服务。可想而知,性能的提升还是大很多的!
//
// 怎么启用sendfile?
// 详细配置步骤就不说了,官方wiki已经说明的比较清楚。只提一下注意点吧:
// 1,location 必须 被定义为 internal;
// 2,如果在location中使用alias 一定要注意目录结尾的“/”;
// 3,要注意location 匹配时尽量只用目录名。 我在测试中遇到抓狂的问题。
//
// 先说一下我最终的方案:
// 1,增加一个location作为目标文件的检查,如果存在 就发给internal的location继续处理,如果不存在就rewrite到后端程序处理;
//下载之类可能使用
//主要提高服务器资源性能
rc = sendfile(c->fd, file->file->fd, &offset, file_size); //大数据发送 这就是所谓的零拷贝技术,所以常用来作高性能文件服务器。
3、发送少量数据的处理:
读取数据
if (iov == NULL) {
return NGX_CHAIN_ERROR;
}
发送数据
//应该是小数据发送
// 将多个数据存储在一起,将驻留在两个或更多的不连接的缓冲区中的数据一次写出去。
// UNIX和WINSOCK提供了不同的实现方法UNIX系统下,使用writev,可以指定一系列的缓冲区,收集要写的数据,使可以安排数据保存在多个缓冲区中,然后同时写出去,从而避免出现Nagle和延迟ACK算法的相互影响。
rc = writev(c->fd, header.elts, header.nelts);
阅读(2718) | 评论(0) | 转发(0) |