TCP 粘包 拆包

TCP 粘(nián)包 拆包 这两个词并没有一一对应的英文 tcp 文档中并不存在 粘包拆包的描述, 一般粘包抓包是指应用层协议的边界定义和数据报读取/处理的问题 tcp是面向流的协议, 在tcp上接收数据报(datagram) 就需要处理 流(stream) 到 数据报的过程. https://www.zhihu.com/question/20210025 TCP是面向字节流的协议,就是没有界限的一串数据,本没有“包”的概念,“粘包”和“拆包”一说是为了有助于形象地理解这两种现象。 粘包拆包发生场景 因为TCP是面向流,没有边界,而操作系统在发送TCP数据时,会通过缓冲区来进行优化,例如缓冲区为1024个字节大小。 如果一次请求发送的数据量比较小,没达到缓冲区大小,TCP则会将多个请求合并为同一个请求进行发送,这就形成了粘包问题。 如果一次请求发送的数据量比较大,超过了缓冲区大小,TCP就会将其拆分为多次发送,这就是拆包。 正常的理想情况,两个包恰好满足TCP缓冲区的大小或达到TCP等待时长,分别发送两个包; 粘包:两个包较小,间隔时间短,发生粘包,合并成一个包发送; 拆包:一个包过大,超过缓存区大小,拆分成两个或多个包发送; 拆包和粘包:Packet1过大,进行了拆包处理,而拆出去的一部分又与Packet2进行粘包处理。 粘包 TCP协议中,发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。 TCP网络通信时候会发生粘包/拆包的问题,接下来探讨其解决之道。 什么是粘包/拆包 一般所谓的 TCP 粘包是在一次接收数据不能完全地体现一个完整的消息数据。 TCP通讯为何存在粘包呢?主要原因是TCP是以流的方式来处理数据,再加上网络上 MTU 的往往小于在应用处理的消息数据,所以就会引发一次接收的数据无法满足消息的需要,导致粘包的存在。 处理粘包的唯一方法就是制定应用层的数据通讯协议,通过协议来规范现有接收的数据是否满足消息数据的需要。 情况分析 TCP 粘包通常在流传输中出现,UDP 则不会出现粘包,因为 UDP 有消息边界,发送数据段需要等待缓冲区满了才将数据发送出去,当满的时候有可能不是一条消息而是几条消息合并在换中去内,在成粘包;另外接收数据端没能及时接收缓冲区的包,造成了缓冲区多包合并接收,也是粘包。 解决办法 消息定长,报文大小固定长度,不够空格补全,发送和接收方遵循相同的约定,这样即使粘包了通过接收方编程实现获取定长报文也能区分。 包尾添加特殊分隔符,例如每条报文结束都添加回车换行符 (例如FTP协议) 或者指定特殊字符作为报文分隔符,接收方通过特殊分隔符切分报文区分。例如,FTP协议; 将消息分为消息头和消息体,消息头中包含表示信息的总长度 (或者消息体长度) 的字段 更复杂的自定义应用层协议 http://my.oschina.net/imhoodoo/blog/357290 为什么UDP没有粘包? 粘包拆包问题在数据链路层、网络层以及传输层都有可能发生。日常的网络应用开发大都在传输层进行,由于UDP有消息保护边界,不会发生粘包拆包问题,因此粘包拆包问题只发生在TCP协议中。 https://cloud.tencent.com/developer/article/1804413 Netty对粘包和拆包问题的处理 Netty对解决粘包和拆包的方案做了抽象,提供了一些解码器 (Decoder)来解决粘包和拆包的问题。如: LineBasedFrameDecoder:以行为单位进行数据包的解码; DelimiterBasedFrameDecoder:以特殊的符号作为分隔来进行数据包的解码; FixedLengthFrameDecoder:以固定长度进行数据包的解码; LenghtFieldBasedFrameDecode:适用于消息头包含消息长度的协议 (最常用); 基于Netty进行网络读写的程序,可以直接使用这些Decoder来完成数据包的解码。对于高并发、大流量的系统来说,每个数据包都不应该传输多余的数据 (所以补齐的方式不可取),LenghtFieldBasedFrameDecode更适合这样的场景。 小结 TCP协议粘包拆包问题是因为TCP协议数据传输是基于字节流的,它不包含消息、数据包等概念,需要应用层协议自己设计消息的边界,即消息帧 (Message Framing)。如果应用层协议没有使用基于长度或者基于终结符息边界等方式进行处理,则会导致多个消息的粘包和拆包。 虽然很多框架中都有现成的解决方案,比如Netty,但底层的原理我们还是要清楚的,而且还要知道有这么会事,才能更好的结合场景进行使用。

2015-09-17 · 1 min · 69 words · -

linux jmeter 分布式测试

linux jmeter 分布式测试 http://www.51testing.com/html/55/383255-847895.html 我将使用3台linux测试机部署jmeter,部署方法也是非常简单,打包后放在指定的目录就ok了, 先定义了 A服务器:控制机 B C服务器为负载机 主意如果要运行jmeter一定要安装1.6以上版本的jdk并正确配置环境变量, 首先在bin目录下 启动B C 服务器 jmeter的jmeter-server服务器,如果启动报错请根据报错内容检查对应的环境配置,我这边报错的原因是hosts没有指定地址, jmeter-server正常启动会提示"创建远程服务" 接下来是准备测试脚本,可以在windows环境下先创建jmx文件,主意最好不要添加监听器,应为命令行启动的话监听器可能会占用资源而且有没有任何视图效果. 将生成好的jmx文件上传到A服务器 jmeter目录的bin目录下,然后在bin目录下创建xx.jtl文件.jtl文件用来接收测试中产生的测试结果 好了 现在进bin目录 打入启动命令,当然你也可以用绝对路径来运行启动命令 ./jmeter -n -t xx.jmx -R B服务器ip,C服务器ip -l $jmeterpath/bin/xx.jtl 参数说明 : -n 告诉jmeter使用nogui模式运行测试 -t 执行的测试脚本名 -R 后面跟随负载机的ip地址 ,注意用逗号隔开 -l 后面跟着测试结果记录的路径与文件名,主意这个文件jmeter不会自己创建,请预先创建好, 万事俱备 按下回车 ! 就开始虐待你的测试项目吧 测试完成后把xx.jtl文件下载到windows机上在不同的监听器上分析测试结果 如果想修改测试脚本,起始也不必把脚本在windows机上打开gui界面修改,直接编辑.jmx文件 你就可以看到许多熟悉的名字,这里就简单介绍几个 5 5 ...

2015-09-16 · 1 min · 67 words · -

http load

http load http://blog.chinaunix.net/uid-488742-id-2113649.html http://www.acme.com/software/http_load/ Web测试工具 http_load 一个httpd 压力测试工具 2007-12-02 09:42:15 分类: LINUX 到http://www.acme.com/software/http_load/ 下载http_load ,安装也很简单直接make;make instlall 就行。 http_load的标准的两个例子是: http_load -parallel 5 -fetches 1000 urls.txt http_load -rate 2 -seconds 300 urls.txt 例子只是个参考,参数其实可以自由组合,参数之间的选择并没有什么限制。比如你写成http_load -parallel 5 -seconds 300 urls.txt也是可以的。我们把参数给大家简单说明一下。-parallel 简写-p : 含义是并发的用户进程数。 -fetches 简写-f : 含义是总计的访问次数 -rate 简写-p : 含义是每秒的访问频率 -seconds简写-s : 含义是总计的访问时间 urls.txt 是一个url 列表,每个url 单独的一行。当然也可以直接跟一个url 而不是url 列表文件。 实例: http_load -rate 5 -seconds 10 urls 49 fetches, 2 max parallel, 289884 bytes, in 10.0148 seconds ...

2015-09-16 · 1 min · 200 words · -

Web服务 压力测试工具,goreplay gor, http_load、webbench、apabhe ab、siege

Web服务 压力测试工具,goreplay gor, http_load、webbench、apabhe ab、siege goreplay, Gor https://github.com/buger/goreplay 一、http_load 程序非常小,解压后也不到100K http_load以并行复用的方式运行,用以测试web服务器的吞吐量与负载。但是它不同于大多数压力测试工具,它可以以一个单一的进程运行,一般不会把客户机搞死。还可以测试HTTPS类的网站请求。 下载地址: http://soft.vpser.net/test/http_load/http_load-12mar2006.tar.gz 安装 tar zxvf http_load-12mar2006.tar.gz cd http_load-12mar2006 make && make install ...

2015-09-15 · 4 min · 674 words · -

LinkedBlockingQueue

LinkedBlockingQueue 基于链表的阻塞队列,同 ArrayBlockingQueue 类似,其内部也维持着一个数据缓冲队列 (该队列是一个链表) ,生产者存入的数据会缓存在队列内部,生产者立即返回;只有当队列缓冲区达到最大值缓存容量时 (LinkedBlockingQueue 可以通过构造函数指定该值) ,才会阻塞生产者队列,直到消费者从队列中消费掉一份数据,生产者线程会被唤醒,反之对于消费者这端的处理也基于同样的原理。而LinkedBlockingQueue 之所以能够高效的处理并发数据,还因为其对于生产者端和消费者端 分别采用了独立的锁 来控制数据同步,这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。 作为开发者,我们需要注意的是,如果构造一个 LinkedBlockingQueue 对象,而没有指定其容量大小,LinkedBlockingQueue 会默认一个类似无限大小的容量 (Integer.MAX_VALUE) ,这样的话,如果生产者的速度一旦大于消费者的速度,也许还没有等到队列满阻塞产生,系统内存就有可能已被消耗殆尽了。 此队列按 FIFO (先进先出) 排序元素。队列的头部 是在队列中时间最长的元素。队列的尾部 是在队列中时间最短的元素。 新元素插入到队列的尾部,并且队列检索操作会获得位于队列头部的元素。链接队列的吞吐量通常要高于基于数组的队列, 但是在大多数并发应用程序中,其可预知的性能要低。 可选的容量范围构造方法参数作为防止队列过度扩展的一种方法。 如果未指定容量,默认容量为 Integer.MAX_VALUE ,容量范围可以在构造方法参数中指定作为防止队列过度扩展。 此对象是线程阻塞-线程安全的 不接受 null 元素 它实现了BlockingQueue接口。 实现了 Collection 和 Iterator 接口的所有可选方法。 在JDK5/6中,LinkedBlockingQueue和ArrayBlocingQueue等对象的poll(long timeout, TimeUnit unit)存在内存泄露Leak的对象AbstractQueuedSynchronizer.Node,据称JDK5会在Update12里Fix,JDK6会在Update2里Fix 下面介绍几种常用的方法: 定义一个输出方法: static void v(Object s){System.out.println(s.toString());} LinkedBlockingQueue bq=new LinkedBlockingQueue(); for(int i=0;i<100;i++) { bq.add(“i”+i);//如果空间已满,此方法会抛出异常,所以这就是put,或者offer方法的优势所在 } String s1=bq.take();//i0 String s2=bq.take();//i1 bq.offer(“ix”,5,TimeUnit.SECONDS);//在尾部插入一个元素,如果有必要 ,等待 指定的时间,使得队列变得可用。返回boolean值 表示是否插入成功。 ...

2015-09-14 · 2 min · 426 words · -

LinkedTransferQueue

LinkedTransferQueue LinkedTransferQueue是在JDK1.7时,J.U.C包新增的一种比较特殊的阻塞队列,它除了具备阻塞队列的常用功能外,还有一个比较特殊的transfer方法。 我们知道,在普通阻塞队列中,当队列为空时,消费者线程(调用take或poll方法的线程)一般会阻塞等待生产者线程往队列中存入元素。而LinkedTransferQueue的transfer方法则比较特殊: 当有消费者线程阻塞等待时,调用transfer方法的生产者线程不会将元素存入队列,而是直接将元素传递给消费者; 如果调用transfer方法的生产者线程发现没有正在等待的消费者线程,则会将元素入队,然后会阻塞等待,直到有一个消费者线程来获取该元素。 有一篇论文讨论了其算法与性能: 地址: http://www.cs.rice.edu/~wns1/papers/2006-PPoPP-SQ.pdf LinkedTransferQueue 实现了一个重要的接口 TransferQueue, 该接口含有下面几个重要方法: transfer(E e) 若当前存在一个正在等待获取的消费者线程,即立刻移交之;否则,会插入当前元素e到队列尾部,并且等待进入阻塞状态,到有消费者线程取走该元素。 tryTransfer(E e) 若当前存在一个正在等待获取的消费者线程 (使用take()或者poll()函数) ,使用该方法会即刻转移/传输对象元素e; 若不存在,则返回false,并且不进入队列。这是一个不阻塞的操作。 tryTransfer(E e, long timeout, TimeUnit unit) 若当前存在一个正在等待获取的消费者线程,会立即传输给它; 否则将插入元素e到队列尾部,并且等待被消费者线程获取消费掉, 若在指定的时间内元素e无法被消费者线程获取,则返回false,同时该元素被移除。 hasWaitingConsumer() 判断是否存在消费者线程 getWaitingConsumerCount() 获取所有等待获取元素的消费线程数量 其实transfer方法在SynchronousQueue的实现中就已存在了,只是没有做为API暴露出来。SynchronousQueue有一个特性:它本身不存在容量,只能进行线程之间的 元素传送。SynchronousQueue在执行offer操作时,如果没有其他线程执行poll,则直接返回false.线程之间元素传送正是通过transfer方法完成的。 有一个使用案例,我们知道ThreadPoolExecutor调节线程的原则是: 先调整到最小线程,最小线程用完后,他会将优先将任务放入缓存队列(offer(task)),等缓冲队列用完了,才会向最大线程数调节。这似乎与我们所理解的线程池模型有点不同。我们一般采用增加到最大线程后,才会放入缓冲队列中,以达到最大性能。ThreadPoolExecutor代码片段: public void execute(Runnable command) { if (command == null) throw new NullPointerException(); if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) { if (runState == RUNNING && workQueue.offer(command)) { if (runState != RUNNING || poolSize == 0) ensureQueuedTaskHandled(command); } else if (!addIfUnderMaximumPoolSize(command)) ...

2015-09-14 · 1 min · 160 words · -

SynchronousQueue

SynchronousQueue http://wsmajunfeng.iteye.com/blog/1629352/ SynchronousQueue 是这样一种阻塞队列,其中每个 put 必须等待一个 take, 反之亦然。同步队列没有任何内部容量,甚至连一个队列的容量都没有。 不能在同步队列上进行 peek,因为仅在试图要取得元素时,该元素才存在; 除非另一个线程试图移除某个元素, 否则也不能 (使用任何方法) 添加元素; 也不能迭代队列, 因为其中没有元素可用于迭代。队列的头是尝试添加到队列中的首个已排队线程元素; 如果没有已排队线程,则不添加元素并且头为 null。 对于其他 Collection 方法 (例如 contains) ,SynchronousQueue 作为一个空集合。此队列不允许 null 元素。 它非常适合于传递性设计,在这种设计中,在一个线程中运行的对象要将某些信息、 事件或任务传递给在另一个线程中运行的对象,它就必须与该对象同步。 对于正在等待的生产者和使用者线程而言,此类支持可选的公平排序策略。默认情况下不保证这种排序。 但是,使用公平设置为 true 所构造的队列可保证线程以 FIFO 的顺序进行访问。 公平通常会降低吞吐量,但是可以减小可变性并避免得不到服务。 注意1: 它一种阻塞队列,其中每个 put 必须等待一个 take,反之亦然。同步队列没有任何内部容量,甚至连一个队列的容量都没有。 注意2: 它是线程安全的,是阻塞的。 注意3:不允许使用 null 元素。 注意4: 公平排序策略是指调用 put 的线程之间, 或 take 的线程之间。公平排序策略可以查考 ArrayBlockingQueue 中的公平策略。 注意5: SynchronousQueue 的以下方法: iterator() 永远返回空,因为里面没东西。 peek() 永远返回null。 put() 往queue放进去一个element以后就一直wait直到有其他thread进来把这个element取走。 offer() 往queue里放一个element后立即返回,如果碰巧这个element被另一个thread取走了,offer方法返回true,认为offer成功;否则返回false。 offer(2000, TimeUnit.SECONDS) 往queue里放一个element但是等待指定的时间后才返回,返回的逻辑和offer()方法一样。 take() 取出并且remove掉queue里的element (认为是在queue里的。。。) ,取不到东西他会一直等。 ...

2015-09-14 · 1 min · 110 words · -

gentoo

gentoo mount /dev/sda3 /mnt/gentoo mount /dev/sda1 /mnt/gentoo/boot chmod 1777 /mnt/gentoo/tmp mount -t proc proc /mnt/gentoo/proc mount -rbind /sys /mnt/gentoo/sys mount -make-rslave /mnt/gentoo/sys mount -rbind /dev /mnt/gentoo/dev mount -make-rslave /mnt/gentoo/dev mount -t tmpfs -o nosuid,nodev,noexec shm /dev/shm chmod 1777 /dev/shm chroot /mnt/gentoo /bin/bash source /etc/profile export PS1="(chroot) $PS1" the minimal install cds have the ability to run isohybrid on them and then you can dd that image to a removable device. ...

2015-09-12 · 2 min · 379 words · -

logstash+ElasticSearch+Kibana VS Splunk

logstash+ElasticSearch+Kibana VS Splunk http://blog.csdn.net/firefoxbug/article/details/8018377 最近帮磊哥移植一套开源的日志管理软件,替代Splunk. Splunk是一个功能强大的日志管理工具,它不仅可以用多种方式来添加日志,生产图形化报表,最厉害的是它的搜索功能 - 被称为"Google for IT"。Splunk有免费和收费版,最主要的差别在于每天的索引容量大小 (索引是搜索功能的基础) ,免费版每天最大为500M。在使用免费版时,如果在30天之内,有7天的索引数据量超过500M,那么就不可以再搜索了. 我熟悉了几天logstash,然后用ElasticSearch进行搜索,最后用Kibana来作为漂亮的三方界面,总体上不错!果然是开源的力量.整个搭建的过程比较复杂,东西比较多,有java,有ruby,有python一些列的.先介绍下三个开源项目 Logstash is very useful and versatile. It’s made of JRuby (Java+Ruby). You can specify inputs and outputs as well as filters. It supports various input types. One of them is “Linux Syslog”. Which means, you do not have to install logging agent on every server increasing the overall load of the server. Your default rsyslog client will do just fine. Then comes the filtering part, after taking input, you can filter out logs within Logstash itself. It’s awesome but it didn’t serve any purpose for me as I wanted to index every log. Next is the output part, Logstash can output logs on standard output (why would anyone want that). But as with input, it supports multiple output types too. One of them is Elasticsearch. ...

2015-09-10 · 1 min · 195 words · -

Maven内置变量

Maven内置变量 Maven内置变量说明: ${basedir} 项目根目录 ${project.build.directory} 构建目录,缺省为target ${project.build.outputDirectory} 构建过程输出目录,缺省为target/classes ${project.build.finalName} 产出物名称,缺省为${project.artifactId}-${project.version} ${project.packaging} 打包类型,缺省为jar ${project.xxx} 当前pom文件的任意节点的内容

2015-09-10 · 1 min · 14 words · -

nmcli

nmcli 跨树协议 (STP) nmcli con show # 创建 br0 启用 stp nmcli con add type bridge ifname br0 # 禁用 stp nmcli con add type bridge ifname br0 stp no # 把 enp0s20f0u2 加入 br0 nmcli con add type bridge-slave ifname enp0s20f0u2 master br0 nmcli connection show --active nmcli connection down enp0s20f0u2 nmcli connection up bridge-br0 nmcli connection up bridge-slave-enp0s20f0u2

2015-09-09 · 1 min · 60 words · -

java metrics

java metrics Metrics 类型 Counters Counter 就是计数器, Counter 只是用 Gauge 封装了 AtomicLong Gauges 最简单的度量指标,只有一个简单的返回值,例如,我们想衡量一个待处理队列中任务的个数 Meters Meter度量一系列事件发生的速率 (rate),例如 TPS, Meters 会统计最近 1分钟,5分钟,15分钟,还有全部时间的速率。 Histograms Histogram 统计数据的分布情况。比如最小值,最大值,中间值,还有中位数,75百分位, 90百分位, 95百分位, 98百分位, 99百分位, 和 99.9百分位的值 (percentiles)。 Timers Timer其实是 Histogram 和 Meter 的结合, histogram 某部分代码/调用的耗时, meter 统计 TPS 其他 除此之外,Metrics还提供了 HealthCheck 用来检测某个某个系统是否健康,例如数据库连接是否正常。还有Metrics Annotation,可以很方便地实现统计某个方法,某个值的数据。感兴趣的可以点进链接看看。 https://mvnrepository.com/artifact/io.dropwizard.metrics/metrics-core gradle dependency compile group: 'io.dropwizard.metrics', name: 'metrics-core', version: '3.1.2' private static final MetricRegistry metrics = new MetricRegistry(); private static ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build(); private static final Meter meter = metrics.meter(name(DruidTest.class, "request")); meter.mark(); reporter.report(); //Timer public class TimerTest { public static Random random = new Random(); public static void main(String[] args) throws InterruptedException { MetricRegistry registry = new MetricRegistry(); ConsoleReporter reporter = ConsoleReporter.forRegistry(registry).build(); reporter.start(1, TimeUnit.SECONDS); Timer timer = registry.timer(MetricRegistry.name(TimerTest.class,"get-latency")); Timer.Context ctx; while(true){ ctx = timer.time(); Thread.sleep(random.nextInt(1000)); ctx.stop(); } } } http://www.cnblogs.com/nexiyi/p/metrics_sample_1.html http://blog.csdn.net/hengyunabc/article/details/44072285 http://wuchong.me/blog/2015/08/01/getting-started-with-metrics/ ...

2015-09-08 · 1 min · 172 words · -

HTTP Header ETag

HTTP Header ETag HTTP Header中的ETag 分类: java web2013-09-02 20:14 1375人阅读 评论(0) 收藏 举报 目录? 原文参考百度百科: http://baike.baidu.com/view/3039264.htm 概念 Etag[1] 是URL的Entity Tag,用于标示URL对象是否改变,区分不同语言和Session等等。具体内部含义是使服务器控制的,就像Cookie那样。 HTTP协议规格说明定义ETag为"被请求变量的实体值"。另一种说法是,ETag是一个可以与Web资源关联的记号 (token) 。典型的Web资源可以一个Web页,但也可能是JSON或XML文档。服务器单独负责判断记号是什么及其含义,并在HTTP响应头中将其传送到客户端,以下是服务器端返回的格式: ETag:“50b1c1d4f775c61:df3"客户端的查询更新格式是这样的: If-None-Match : W / “50b1c1d4f775c61:df3"如果ETag没改变,则返回状态304然后不返回,这也和Last-Modified一样。测试Etag主要在断点下载时比较有用。 性能 聪明的服务器开发者会把ETags和GET请求的"If-None-Match"头一起使用,这样可利用客户端 (例如浏览器) 的缓存。因为服务器首先产生ETag,服务器可在稍后使用它来判断页面是否已经被修改。本质上,客户端通过将该记号传回服务器要求服务器验证其 (客户端) 缓存。 其过程如下: 客户端请求一个页面 (A) 。 服务器返回页面A,并在给A加上一个ETag。 客户端展现该页面,并将页面连同ETag一起缓存。 客户再次请求页面A,并将上次请求时服务器返回的ETag一起传递给服务器。 服务器检查该ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304 (未修改——Not Modified) 和一个空的响应体。 优势 有些URL是多语言的网页,相同的URL会返回不同的东西。还有不同的Session有不同的Cookie也就有不同的内容。这种情况下如果过 Proxy,Proxy就无法区分导致串门,只能简单的取消cache功能。Etag解决了这个问题,因为它能区分相同URL不同的对象。 老的HTTP标准里有个Last-Modified+If-Modified-Since表明URL对象是否改变。Etag也具有这种功能,因为对象改变也造成Etag改变,并且它的控制更加准确。Etag有两种用法 If-Match/If-None-Match,就是如果服务器的对象和客户端的对象ID (不) 匹配才执行。这里的If-Match/If-None- Match都能一次提交多个Etag。If-Match可以在Etag未改变时断线重传。If-None-Match可以刷新对象 (在有新的Etag时返回) 。 Etag中有种Weak Tag,值为 W/“xxxxx”。他声明Tag是弱匹配的,只能做模糊匹配,在差异达到一定阀值时才起作用。 Etag对于cache CGI页面很有用。特别是论坛,论坛有办法为每个帖子页面生成唯一的Etag,在帖子未改变时,查看话题属性比较Etag就能避免刷新帖子,减少CGI操作和网络传输。比如论坛中看帖就返回Etag,减少论坛负担。 Etag在不同URL之间没有可比性,也就是不同URL相同Etag没有特别意义。 原理 请求流程 Etag由服务器端生成,客户端通过If-Match或者说If-None-Match这个条件判断请求来验证资源是否修改。常见的是使用If-None-Match.请求一个文件的流程可能如下: ====第一次请求=== 1.客户端发起 HTTP GET 请求一个文件; 2.服务器处理请求,返回文件内容和一堆Header,当然包括Etag(例如"2e681a-6-5d044840”)(假设服务器支持Etag生成和已经开启了Etag).状态码200 ====第二次请求=== ...

2015-09-07 · 1 min · 108 words · -

chrome sdch

chrome sdch sdch: chrome 支持的新HTTP传输压缩算法 我们知道,为了加快网络传输,一般都使用gzip对文本进行压缩。如果你现在用最新版的chrome去访问页面,然后打开network控制面板,查看http headers,细心的你会发现在Request Headers里的Accept-Encoding不再是gzip,deflate,而是多了个sdch,变成了gzip,deflate,sdch。如图: SDCH到底是什么 sdch是Shared Dictionary Compression over HTTP的缩写,即通过字典压缩算法对各个页面中相同的内容进行压缩,减少相同的内容的传输。如: 一个网站中一般都是共同的头部和尾部,甚至一些侧边栏也是共同的。之前的方式每个页面打开的时候这些共同的信息都要重新加载,但使用SDCH压缩方式的话,那些共同的内容只用传输一次就可以了。 sdch主要分为3个部分: 首次请求,下载字典,之后的请求。 这种方式最开始的时候是Google工具栏里为IE准备的,目前Chrome已经完全支持了,不过暂时还没发现哪个网站在使用。 SDCH与ajax+pushState SDCH压缩方式是为了减少相同内容的传输的,同时之前介绍的ajax+pushState也是减少相同内容的传输,他们想达到的效果是一样的。只是SDCH是Google出的,可能今后一段时间只有Chrome浏览器支持,但pushState是HTML5的一个标准,目前已经有Chrome和Firefox支持,之后会有越来越多的浏览器支持。 个人觉得SDCH可能没有什么太大的发展,但可以作为一个新方向研究,并且在合适的时候添加到标准里,让网络传输越来越迅速。

2015-09-06 · 1 min · 21 words · -

golang 程序 too many open files

golang 程序 too many open files Go 程序 报错 too many open files 程序 报错之后 查看 进程 打开的 文件 lsof -p 14092 |wc -l, 1032 排除掉 内存映射文件(mem), 列标题, cwd, rtd, txt, 刚好 1024, lsof -p 14092 看到打开的 fd 最大值 1023u shell 下 查看系统的文件数设置 ulimit -a ulimit -Hn ulimit -Sn 65535 systemd limit https://unix.stackexchange.com/questions/345595/how-to-set-ulimits-on-service-with-systemd Go rlimit https://stackoverflow.com/questions/17817204/how-to-set-ulimit-n-from-a-golang-program wangyue.dev/lsof wangyue.dev/ulimit wangyue.dev/systemd/script

2015-09-02 · 1 min · 59 words · -

Linux单机TCP并发连接

Linux单机 TCP 并发连接 http://blog.csdn.net/kobejayandy/article/details/47127991 总结下服务端对于tcp连接的限制与提高tcp连接数的方法,可能工作中永远不会用到,但对于网络知识理解会有帮助。1.服务端与16位的端口号 (最大65535) 没什么关系 服务端ip+port(监听端口) + 客户端ip+port 决定了一条连接,客户端连接服务器后,服务端并没有又分配一个物理端口与客户端连接。其实所有的数据还是通过监听端口接收与发送的 (不论全双工与半双工,反正都是双工的) ,只不过多了一个逻辑上的socket。这些都应该是网卡上的事情,当接收到一个字节流的时候,网卡就会回调给操作系统,回调的时候会告诉操作系统客户端ip+port,假如是epoll模型,那么这次可能只接收了几个字节,回调那个新的socket的特定方法。然后下一次从监听端口回调上来的数据可能是另外的一个逻辑上的socket,各自互不影响。 2.内存限制 系统为每个TCP 连接分配一个TCP 控制块(TCP control block or TCB)。一个tcb控制块大概要占用1k多的内存,假如百万连接,1个tcb占用1k内存,那么就需要1G的内存了,这还是理想情况,一般情况下tcb要大于1k内存。当每个连接上在有数据传输的时候,同时需要的内存就更大了。 另外需要设置的tcp参数有tcp的读写缓冲区,默认为86k,都可以改成4k。此外需要修改tcp_mem的值。 tcp_mem(3个INTEGER变量): low, pressure, high low: 当TCP使用了低于该值的内存页面数时,TCP不会考虑释放内存。 pressure: 当TCP使用了超过该值的内存页面数量时,TCP试图稳定其内存使用,进入pressure模式,当内存消耗低于low值时则退出pressure状态。 high: 允许所有tcp sockets用于排队缓冲数据报的页面量,当内存占用超过此值,系统拒绝分配socket,后台日志输出"TCP: too many of orphaned sockets"。 3.文件句柄限制 每个socket都是一个文件句柄,linux下文件句柄限制,包括linux允许的最大文件句柄,linux允许的最大同时活动的文件句柄。 4.网卡限制 千兆网卡,上限满负荷工作,大概有600兆左右,单位为b,除以8为75k/单个连接。这个一般可以满足。 参考http://www.blogjava.net/yongboy/archive/2013/04/11/397677.html linux下需要修改的地方有: echo “* - nofile 1048576” » /etc/security/limits.conf #open file resource limit 是linux中process可以打开的文件句柄数量。 echo “fs.file-max = 1048576” » /etc/sysctl.conf #系统最大允许的文件描述符 echo “net.ipv4.ip_local_port_range = 1024 65535” » /etc/sysctl.conf #可以使用的端口范围,主要为了测试时候使用 ...

2015-08-31 · 1 min · 100 words · -

Java NIO 框架 Netty, Mina, Grizzly

Java NIO 框架 Netty, Mina, Grizzly Netty Netty是一款异步的事件驱动的网络应用框架和工具,用于快速开发可维护的高性能、高扩展性协议服务器和客户端。也就是说,Netty是一个NIO客户端/服务器框架,支持快速、简单地开发网络应用,如协议服务器和客户端。它极大简化了网络编程,如TCP和UDP socket 服务器。 Mina Mina(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络应用程序提供了非常便利的框架。当前发行的 Mina 版本2.04支持基于 Java NIO 技术的 TCP/UDP 应用程序开发、串口通讯程序,Mina 所支持的功能也在进一步的扩展中。目前,正在使用 Mina的应用包括: Apache Directory Project、AsyncWeb、AMQP (Advanced Message Queuing Protocol) 、RED5 Server (Macromedia Flash Media RTMP) 、ObjectRADIUS、 Openfire等等。 Grizzly: Grizzly是一种应用程序框架,专门解决编写成千上万用户访问服务器时候产生的各种问题。使用JAVA NIO作为基础,并隐藏其编程的复杂性。容易使用的高性能的API。带来非阻塞socketd到协议处理层。利用高性能的缓冲和缓冲管理使用高性能的线程池。 OK,我们现在可以看看三者的简单对比了。 首先,从设计的理念上来看,Mina的设计理念是最为优雅的。当然,由于Netty的主导作者与Mina的主导作者是同一人,出自同一人之手的Netty在设计理念上与Mina基本上是一致的。而Grizzly在设计理念上就较差了点,几乎是Java NIO的简单封装。 其次,从项目的出身来看,Mina出身于开源界的大牛Apache组织,Netty出身于商业开源大亨Jboss,而Grizzly则出身于土鳖Sun公司。从其出身可以看到其应用的广泛程序,到目前为止,我见到业界还是使用Mina多一些,而Netty也在慢慢的应用起来,而Grizzly则似乎只有Sun自已的项目使用了,如果还有其他的公司或开源项目在使用,那就算我孤陋寡闻。 最后,从入门的文档来说,由于Mina见世时间相对较长,官方以及民间的文档与入门示例都相当的多。Netty的官方文档也做得很好,而民间文档就要相对于Mina少一些了。至于Grizzly,不管是官方还是民间,都很少见到其文档。 http://www.blogjava.net/javagrass/archive/2011/07/05/353680.html

2015-08-31 · 1 min · 52 words · -

NIO

NIO JavaNIO 非堵塞应用通常适于I/O 读写等方面, 我们知道, 系统运行的性能瓶颈通常在I/O读写,包括对网络和磁盘的操作上, 过去,在打开一个I/O通道后,read()将一直等待在端口一边读取字节内容,如果没有内容进来,read()也是傻傻的等,这会影响我们程序继续做其他事情, 那么改进做法就是开设线程, 让线程去等待, 但是这样做也是相当耗费资源的(线程调度) Java NIO 非堵塞技术实际是采取 Reactor 模式, 或者说是 Observer 模式为我们监察I/O端口,如果有内容进来, 会自动通知我们,这样,我们就不必开启多个线程死等, 从外界看, 实现了流畅的I/O读写,不堵塞了。 Java NIO 出现不只是一个技术性能的提高,你会发现网络上到处在介绍它,因为它具有里程碑意义,从JDK1.4开始,Java开始提高性能相关的功能,从而使得Java在底层或者并行分布式计算等操作上已经可以和C或Perl等语言并驾齐驱。 IO 模型主要分类 同步 synchronous IO 异步 asynchronous IO 阻塞 blocking 非阻塞 (non-blocking) NIO 同步阻塞, blocking-IO, BIO 同步非阻塞, non-blocking-IO, NIO 异步阻塞: 不存在的… 异步非阻塞, Asynchronous-non-blocking-IO, AIO 同步, 异步 同步和异步关注的是消息通信机制 ( synchronous communication/ asynchronous communication ) 同步: 发送一个请求,等待返回, 再发送下一个请求,同步可以避免出现死锁,脏读的发生。 异步: 发送一个请求,不等待返回, 随时可以再发送下一个请求,可以提高效率,保证并发。 所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由调用者主动等待这个调用的结果。而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。 举个通俗的例子: 你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了 (可能是5秒,也可能是一天) 告诉你结果 (返回结果) 。而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了 (不返回结果) 。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。 ...

2015-08-31 · 2 min · 294 words · -

Dubbo

Dubbo Dubbo, |ˈdʌbəʊ| Dubbo3 推荐使用 IDL 定义跨语言服务 Dubbo 默认的协议是 dubbo 协议 (协议和框架同名),而 dubbo 协议默认指定的序列化方式是 hessian2 IDL 接口描述语言 (Interface description language,缩写IDL) helloworld https://github.com/dubbogo/dubbo-samples.git export CONF_PROVIDER_FILE_PATH="/home/wiloon/tmp/server.yml" export CONF_CONSUMER_FILE_PATH="/home/wiloon/tmp/client.yml" export APP_LOG_CONF_FILE="/home/wiloon/tmp/log.yml" 服务发现 流式通信 负载均衡 流量调度/流量治理 Dubbo 支持流控策略在运行态动态生效,无需重新部署。 Apache Dubbo 是一款微服务开发框架, 致力于提供高性能和透明化的RPC远程服务调用方案, 以及SOA服务治理方案, 使得应用可通过高性能RPC实现服务的输出和输入功能, 和Spring框架可以无缝集成。 作为一个分布式服务框架,以及SOA治理方案,Dubbo其功能主要包括: 高性能NIO通讯及多协议集成,服务动态寻址与路由,软负载均衡与容错,依赖分析与服务降级等。Dubbo最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合 (或者最大限度地松耦合) 。从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方 (Provider) 和服务消费方 (Consumer) 两个角色。 Dubbo包含远程通讯、集群容错和自动发现三个核心部分。提供透明化的远程方法调用,实现像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。同时具备软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。可以实现服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。 下图来自Dubbo官网,描述了服务注册中心、服务提供方、服务消费方、服务监控中心之间的调用关系,具体如下图所示: 调用关系说明: 服务容器负责启动,加载,运行服务提供者。 服务提供者在启动时,向注册中心注册自己提供的服务。 服务消费者在启动时,向注册中心订阅自己所需的服务。 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。 Dubbo框架设计一共划分了10个层,而最上面的Service层是留给实际想要使用Dubbo开发分布式服务的开发者实现业务逻辑的接口层。图中左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口, 位于中轴线上的为双方都用到的接口。 下面,结合Dubbo官方文档,我们分别理解一下框架分层架构中,各个层次的设计要点: 服务接口层 (Service) : 该层是与实际业务逻辑相关的,根据服务提供方和服务消费方的业务设计对应的接口和实现。 配置层 (Config) : 对外配置接口,以ServiceConfig和ReferenceConfig为中心,可以直接new配置类,也可以通过spring解析配置生成配置类。 ...

2015-08-28 · 1 min · 203 words · -

Spark

Spark http://www.cnblogs.com/jerrylead/archive/2012/08/13/2636115.html 摘要: Spark是继Hadoop之后的新一代大数据分布式处理框架,由UC Berkeley的Matei Zaharia主导开发。我只能说是神一样的人物造就的神器,详情请猛击http://www.spark-project.org/ Created 2012-05-09 Modified 2012-08-13 1 Scala安装 当前,Spark最新版本是0.5,由于我写这篇文档时,版本还是0.4,因此本文下面的所有描述基于0.4版本。 不过淘宝的达人已经尝试了0.5,并写了相关安装文档在此http://rdc.taobao.com/team/jm/archives/tag/spark。 我使用的Spark的版本是0.4,只存在于github上,该版本使用的Scala版本是0.9.1.final。所以先到http://www.scala-lang.org/node/165下载scala-2.9.1.final.tar.gz。解压后放到本地 /opt 下面,在 /etc/profile 里添加 export SCALA_HOME=/opt/scala-2.9.1.final export PATH=$SCALA_HOME/bin:$PATH 2 git安装 由于下载Spark和编译Spark需要git,因此先安装git,安装方法可以到Ubuntu软件中心直接装,也可以apt-get装。装好后需要到https://github.com 去注册一个帐号,我注册的是JerryLead,注册邮箱和密码,然后根据网站上的get-start提示生成RSA密码。 注意: 如果本地之前存在rsa_id.pub,authorized_keys等,将其保存或着将原来的密码生成为dsa形式,这样git和原来的密码都不冲突。 3 Spark安装 首先下载最新的源代码 git clone git://github.com/mesos/spark.git 得到目录spark后,进入spark目录,进入conf子目录,将 spark-env.sh-template 重命名为spark-env.sh,并添加以下代码行: export SCALA_HOME=/opt/scala-2.9.1.final 回到spark目录,开始编译,运行 $ sbt/sbt update compile 这条命令会联网下载很多jar,然后会对spark进行编译,编译完成会提示success [success] Total time: 1228 s, completed May 9, 2012 3:42:11 PM 可以通过运行spark-shell来和spark进行交互。 也可以先运行测试用例./run <class> <params> ./run spark.examples.SparkLR local[2] 在本地启动两个线程运行线性回归。 ./run spark.examples.SparkPi local 在本地启动运行Pi估计器。 更多的例子在examples/src/main/scala里面 3 Spark导出 在使用Spark之前,先将编译好的classes导出为jar比较好,可以 $ sbt/sbt assembly 将Spark及其依赖包导出为jar,放在 core/target/spark-core-assembly-0.4-SNAPSHOT.jar 可以将该jar添加到CLASSPATH里,开发Spark应用了。 一般在开发Spark应用时需要导入Spark一些类和一些隐式的转换,需要再程序开头加入 import spark.SparkContext import SparkContext._ 4 使用Spark交互模式 1. 运行./spark-shell.sh 2. scala> val data = Array(1, 2, 3, 4, 5) //产生data data: Array[Int] = Array(1, 2, 3, 4, 5) 3. scala> val distData = sc.parallelize(data) //将data处理成RDD distData: spark.RDD[Int] = spark.ParallelCollection@7a0ec850 (显示出的类型为RDD) 4. scala> distData.reduce(_+_) //在RDD上进行运算,对data里面元素进行加和 12/05/10 09:36:20 INFO spark.SparkContext: Starting job... 5. 最后运行得到 12/05/10 09:36:20 INFO spark.SparkContext: Job finished in 0.076729174 s res2: Int = 15 5 使用Spark处理Hadoop Datasets Spark可以从HDFS/local FS/Amazon S3/Hypertable/HBase等创建分布式数据集。Spark支持text files,SequenceFiles和其他Hadoop InputFormat。 比如从HDFS上读取文本创建RDD scala> val distFile = sc.textFile("hdfs://m120:9000/user/LijieXu/Demo/file01.txt") 12/05/10 09:49:01 INFO mapred.FileInputFormat: Total input paths to process : 1 distFile: spark.RDD[String] = spark.MappedRDD@59bf8a16 然后可以统计该文本的字符数,map负责处理文本每一行map(_size)得到每一行的字符数,多行组成一个List,reduce负责将List中的所有元素相加。 scala> distFile.map(_.size).reduce(_+_) 12/05/10 09:50:02 INFO spark.SparkContext: Job finished in 0.139610772 s res3: Int = 79 textFile可以通过设置第二个参数来指定slice个数 (slice与Hadoop里的split/block概念对应,一个task处理一个slice) 。Spark默认将Hadoop上一个block对应为一个slice,但可以调大slice的个数,但不能比block的个数小,这就需要知道HDFS上一个文件的block数目,可以通过50070的dfs的jsp来查看。 对于SequenceFile,可以使用SparkContext的sequenceFile[K,V]方法生成RDD,其中K和V肯定要是SequenceFile存放时的类型了,也就是必须是Writable的子类。Spark也允许使用native types去读取,如sequenceFile[Int, String]。 对于复杂的SequenceFile,可以使用SparkContext.hadoopRDD方法去读取,该方法传入JobConf参数,包含InputFormat,key class,value class等,与Hadoop Java客户端读取方式一样。 6 分布式数据集操作 分布式数据集支持两种类型的操作: transformation和action。transformation的意思是从老数据集中生成新的数据集,action是在数据集上进行计算并将结果返回给driver program。每一个Spark应用包含一个driver program用来执行用户的main函数,比如,map就是一个transformation,将大数据集划分处理为小数据集,reduce是action,将数据集上内容进行聚合并返回给driver program。有个例外是reduceByKey应该属于transformation,返回的是分布式数据集。 需要注意的是,Spark的transformation是lazy的,transformation先将操作记录下来,直到接下来的action需要将处理结果返回给driver program的时候。 另一个特性是caching,如果用户指定cache一个数据集RDD,那么该数据集中的不同slice会按照partition被存放到相应不同节点的内存中,这样重用该数据集的时候,效率会高很多,尤其适用于迭代型和交互式的应用。如果cache的RDD丢失,那么重新使用transformation生成。 7 共享变量 与Hadoop的MapReduce不同的是,Spark允许共享变量,但只允许两种受限的变量: broadcast和accumulators。 Broadcast顾名思义是"广播",在每个节点上保持一份read-only的变量。比如,Hadoop的map task需要一部只读词典来处理文本时,由于不存在共享变量,每个task都需要加载一部词典。当然也可以使用DistributedCache来解决。在Spark中,通过broadcast,每个节点存放一部词典就够了,这样从task粒度上升到node粒度,节约的资源可想而知。Spark的broadcast路由算法也考虑到了通信开销。 通过使用SparkContext.broadcast(v)来实现对变量v的包装和共享。

2015-08-28 · 2 min · 216 words · -