java shutdown hook

java shutdown hook 在线上Java程序中经常遇到进程程挂掉,一些状态没有正确的保存下来,这时候就需要在JVM关掉的时候执行一些清理现场的代码。Java中得ShutdownHook提供了比较好的方案。 JDK在1.3之后提供了Java Runtime.addShutdownHook(Thread hook)方法,可以注册一个JVM关闭的钩子,这个钩子可以在以下几种场景被调用: 程序正常退出 使用System.exit() 终端使用Ctrl+C触发的中断 系统关闭 使用Kill pid命令干掉进程 注: 在使用kill -9 pid是不会JVM注册的钩子不会被调用。 http://blog.csdn.net/hemingwang0902/article/details/6207682 http://www.cnblogs.com/nexiyi/p/java_add_ShutdownHook.html

2015-12-30 · 1 min · 19 words · -

tightvnc, tigervnc

tightvnc, tigervnc tighervnc nightly build https://github.com/TigerVNC/tigervnc/releases http://tigervnc.bphinz.com/nightly/ # archlinux pacman -S tigervnc # vncserver # dell desktop vncserver -geometry 1350x670 -dpi 96 -depth 32 :1 vncserver -geometry 1364x768 -dpi 96 -depth 32 :1 vncserver -kill :1 #kill 后面有空格!!! vncviewer 192.168.2.228:1 #edis config file .vnc/xstartup #!/bin/sh startxfce4 exit full screen ctrl+alt+shift+F vncviewer: disable allow jpeg https://unix.stackexchange.com/questions/67096/xterm-warning-tried-to-connect-to-session-manager centos yum -y install tigervnc-server yum -y install tigervnc install xorg start xorg install xfce4 ...

2015-12-25 · 1 min · 74 words · -

apache ab/Apache Bench

apache ab/Apache Bench ApacheBench install yay -S apache-tools sudo yum -y install httpd-tools 格式: ab [options] [http://]hostname[:port]/path # get 请求, 不带 -p参数时 发get请求 ab -n 1 -c 1 -T 'application/x-www-form-urlencoded' "http://127.0.0.1:7000/" #post 请求 ab -n 1 -c 1 -p abpost.txt -T 'application/x-www-form-urlencoded' "http://127.0.0.1:7000/" ab -n 1 -c 1 -p abpost.txt -T 'application/json' "http://127.0.0.1:8080/" 参数: -n requests Number of requests to perform //在测试会话中所执行的请求个数 (本次测试总共要访问页面的次数) 。默认时,仅执行一个请求。 -c concurrency Number of multiple requests to make //一次产生的请求个数 (并发数) 。默认是一次一个。 -t timelimit Seconds to max. wait for responses ...

2015-12-25 · 2 min · 350 words · -

ConcurrentHashMap Collections.synchronizedMap

ConcurrentHashMap Collections.synchronizedMap ConcurrentHashMap, Collections.synchronizedMap和Hashtable讨论 在Java类库中出现的第一个关联的集合类是Hashtable,它是JDK1.0的一部分。 Hashtable提供了一种易于使用的、线程安全的、关联的map功能,这当然也是方便的。然而,线程安全性是凭代价换来的――Hashtable的所有方法都是同步的。此时,无竞争的同步会导致可观的性能代价。Hashtable的后继者HashMap是作为JDK1.2中的集合框架的一部分出现的,它通过提供一个不同步的基类和一个同步的包装器Collections.synchronizedMap,解决了线程安全性问题。 通过将基本的功能从线程安全性中分离开来,Collections.synchronizedMap允许需要同步的用户可以拥有同步,而不需要同步的用户则不必为同步付出代价。Hashtable和synchronizedMap所采取的获得同步的简单方法 (同步Hashtable中或者同步的Map包装器对象中的每个方法) 有两个主要的不足。首先,这种方法对于可伸缩性是一种障碍,因为一次只能有一个线程可以访问hash表。同时,这样仍不足以提供真正的线程安全性,许多公用的混合操作仍然需要额外的同步。 虽然诸如get()和put()之类的简单操作可以在不需要额外同步的情况下安全地完成,但还是有一些公用的操作序列,例如迭代或者put-if-absent (空则放入) ,需要外部的同步,以避免数据争用。有条件的线程安全性同步的集合包装器 synchronizedMap和synchronizedList,有时也被称作有条件地线程安全――所有单个的操作都是线程安全的,但是多个操作组成的操作序列却可能导致数据争用,因为在操作序列中控制流取决于前面操作的结果。 如果一个条目不在Map中,那么添加这个条目。不幸的是,在 containsKey()方法返回到put()方法被调用这段时间内,可能会有另一个线程也插入一个带有相同键的值。如果您想确保只有一次插入,您需要用一个对Map进行同步的同步块将这一对语句包装起来。List.size()的结果在循环的执行期间可能会变得无效,因为另一个线程可以从这个列表中删除条目。可能在进入循环的最后一次迭代之后有一个条目被另一个线程删除了,则List.get()将返回null,抛出一个 NullPointerException异常。那么,采取什么措施才能避免这种情况呢?如果当您正在迭代一个List时另一个线程也可能正在访问这个 List,那么在进行迭代时您必须使用一个synchronized块将这个List包装起来,在List上同步,从而锁住整个List。 这样做虽然解决了数据争用问题,但是在并发性方面付出了更多的代价,因为在迭代期间锁住整个List会阻塞其他线程,使它们在很长一段时间内不能访问这个列表。集合框架引入了迭代器,用于遍历一个列表或者其他集合,从而优化了对一个集合中的元素进行迭代的过程。然而,在java.util集合类中实现的迭代器极易崩溃,也就是说,如果在一个线程正在通过一个Iterator遍历集合时,另一个线程也来修改这个集合,那么接下来的 Iterator.hasNext()或Iterator.next()调用,会抛出ConcurrentModificationException异常。 如果想要防止出现ConcurrentModificationException异常,那么当您正在进行迭代时,您必须使用一个在 Listl上同步的synchronized块将该List包装起来,从而锁住整个List。 (也可以调用List.toArray(),在不同步的情况下对数组进行迭代,但是如果列表比较大的话这样做代价很高) 。 而ConcurrentHashMap是DougLea的util.concurrent包的一部分,现已被集成到 JDK5.0中,它提供比Hashtable或者synchronizedMap更高程度的并发性。而且,对于大多数成功的get()操作它会设法避免完全锁定,其结果就是使得并发应用程序有着非常好的吞吐量。 1 针对吞吐量进行优化 ConcurrentHashMap使用了几个技巧来获得高程度的并发以及避免锁定,包括为不同的hashbucket (桶) 使用多个写锁和使用 JMM 的不确定性来最小化锁被保持的时间——或者根本避免获取锁。对于大多数一般用法来说它是经过优化的,这些用法往往会检索一个很可能在map中已经存在的值。事实上,多数成功的get()操作根本不需要任何锁定就能运行。 (警告: 不要自己试图这样做!想比 JMM 聪明不像看上去的那么容易。util.concurrent类是由并发专家编写的,并且在 JMM 安全性方面经过了严格的同行评审。) 2 多个写锁 我们可以回想一下,Hashtable (或者替代方案 Collections.synchronizedMap) 的可伸缩性的主要障碍是它使用了一个map范围 (map-wide) 的锁,为了保证插入、删除或者检索操作的完整性必须保持这样一个锁,而且有时候甚至还要为了保证迭代遍历操作的完整性保持这样一个锁。这样一来,只要锁被保持,就从根本上阻止了其他线程访问Map,即使处理器有空闲也不能访问,这样大大地限制了并发性。 ConcurrentHashMap摒弃了单一的map范围的锁,取而代之的是由32个锁组成的集合,其中每个锁负责保护hashbucket的一个子集。锁主要由变化性操作 (put()和remove()) 使用。具有32 个独立的锁意味着最多可以有32个线程可以同时修改map。这并不一定是说在并发地对map进行写操作的线程数少于32时,另外的写操作不会被阻塞—— 32对于写线程来说是理论上的并发限制数目,但是实际上可能达不到这个值。但是,32依然比1要好得多,而且对于运行于目前这一代的计算机系统上的大多数应用程序来说已经足够了。 3 map范围的操作 有32个独立的锁,其中每个锁保护hashbucket的一个子集,这样需要独占访问 map的操作就必须获得所有32个锁。一些map范围的操作,比如说size()和isEmpty(),也许能够不用一次锁整个map (通过适当地限定这些操作的语义) ,但是有些操作,比如map重排 (扩大hashbucket的数量,随着map的增长重新分布元素) ,则必须保证独占访问。Java语言不提供用于获取可变大小的锁集合的简便方法。必须这么做的情况很少见,一旦碰到这种情况,可以用递归方法来实现。 JMM概述 在进入 put()、get()和remove()的实现之前,让我们先简单地看一下 JMM。JMM 掌管着一个线程对内存的动作 (读和写) 影响其他线程对内存的动作的方式。由于使用处理器寄存器和预处理cache来提高内存访问速度带来的性能提升,Java语言规范 (JLS) 允许一些内存操作并不对于所有其他线程立即可见。有两种语言机制可用于保证跨线程内存操作的一致性——synchronized和volatile。 按照JLS的说法,“在没有显式同步的情况下,一个实现可以自由地更新主存,更新时所采取的顺序可能是出人意料的。“其意思是说,如果没有同步的话,在一个给定线程中某种顺序的写操作对于另外一个不同的线程来说可能呈现出不同的顺序,并且对内存变量的更新从一个线程传播到另外一个线程的时间是不可预测的。 虽然使用同步最常见的原因是保证对代码关键部分的原子访问,但实际上同步提供三个独立的功能——原子性、可见性和顺序性。原子性非常简单——同步实施一个可重入的 (reentrant) 互斥,防止多于一个的线程同时执行由一个给定的监视器保护的代码块。不幸的是,多数文章都只关注原子性方面,而忽略了其他方面。但是同步在JMM中也扮演着很重要的角色,会引起JVM在获得和释放监视器的时候执行内存壁垒 (memorybarrier) 。 ...

2015-12-24 · 1 min · 83 words · -

Fluent Interface, fluent manner, fluent 风格, 流式接口, 流式风格

Fluent Interface, fluent manner, fluent 风格, 流式接口, 流式风格 这个故事是从下面这样一个对外暴露接口的调用开始的。 queryUserEvent event = new QueryUserEvent(); event.setName(name); event.setAge(18); event.setType(QueryUserEvent.TYPE_NORMAL); event.setSex(QueryUserEvent.SEX_MALE); //... List<User> userList = userService.query(event); 我想做的事情其实很简单,我想查询一个用户列表,可是接口参数的拼装让我感到头疼,这样的代码太过啰嗦,我希望有可读性更好的解决办法。 P兄台说,如果我直接传入一个user对象,是不是可以避开了这个未必带来多少好处的event? User user = new User(); user.setName(name); user.setAge(18); user.setSex(QueryUserEvent.SEX_MALE); // …… List<User> userList = userService.query(user, UserService.QUERY_TYPE_NORMAL); 我有时候会考虑你说的办法的,可是,你没有解决实际的问题,我现在的最大问题在于,这一堆的setXXX方法,它破坏了我构造这个查询条件对象的流畅性。 他紧接着说,那要不然,我们把setXXX方法的劳动省下来,让构造器来替我们完成这个任务吧: User user = new User(name, 18, QueryUserEvent.SEX_MALE, ……); List<User> userList = userService.query(user, UserService.QUERY_TYPE_NORMAL); 我说,你的办法看起来不错,不过有时候按你的办法做,我的构造方法会变得臃肿无比,比如出现十多个参数; 另外还有一个问题,假如说,我的查询条件是简单的 (我只需要根据年龄查询) ,那么其它的参数都要写成null,类似这样子: User user = new User(null, 18, null, null, null, null, ……); List<User> userList = userService.query(user, UserService.QUERY_TYPE_NORMAL); 天,让谁去阅读这样的代码,他都不会喜欢的。 ...

2015-12-23 · 1 min · 205 words · -

Curator

Curator http://macrochen.iteye.com/blog/1366136 Curator 是 Netflix 开源的一套 ZooKeeper 客户端框架. Netflix 在使用ZooKeeper的过程中发现ZooKeeper自带的客户端太底层, 应用方在使用的时候需要自己处理很多事情, 于是在它的基础上包装了一下, 提供了一套更好用的客户端框架. Netflix在用ZooKeeper的过程中遇到的问题, 我们也遇到了, 所以开始研究一下, 首先从他在github上的源码, wiki文档以及Netflix的技术blog入手. 看完官方的文档之后, 发现Curator主要解决了三类问题: 封装ZooKeeper client与ZooKeeper server之间的连接处理; 提供了一套Fluent风格的操作API; 提供ZooKeeper各种应用场景(recipe, 比如共享锁服务, 集群领导选举机制)的抽象封装. Curator列举的ZooKeeper使用过程中的几个问题 初始化连接的问题: 在client与server之间握手建立连接的过程中, 如果握手失败, 执行所有的同步方法(比如create, getData等)将抛出异常 自动恢复(failover)的问题: 当client与一台server的连接丢失,并试图去连接另外一台server时, client将回到初始连接模式 session过期的问题: 在极端情况下, 出现ZooKeeper session过期, 客户端需要自己去监听该状态并重新创建ZooKeeper实例 . 对可恢复异常的处理:当在server端创建一个有序ZNode, 而在将节点名返回给客户端时崩溃, 此时client端抛出可恢复的异常, 用户需要自己捕获这些异常并进行重试 使用场景的问题:Zookeeper提供了一些标准的使用场景支持, 但是ZooKeeper对这些功能的使用说明文档很少, 而且很容易用错. 在一些极端场景下如何处理, zk并没有给出详细的文档说明. 比如共享锁服务, 当服务器端创建临时顺序节点成功, 但是在客户端接收到节点名之前挂掉了, 如果不能很好的处理这种情况, 将导致死锁. Curator主要从以下几个方面降低了zk使用的复杂性: 重试机制:提供可插拔的重试机制, 它将给捕获所有可恢复的异常配置一个重试策略, 并且内部也提供了几种标准的重试策略(比如指数补偿). 连接状态监控: Curator初始化之后会一直的对zk连接进行监听, 一旦发现连接状态发生变化, 将作出相应的处理. zk客户端实例管理:Curator对zk客户端到server集群连接进行管理. 并在需要的情况, 重建zk实例, 保证与zk集群的可靠连接 各种使用场景支持:Curator实现zk支持的大部分使用场景支持(甚至包括zk自身不支持的场景), 这些实现都遵循了zk的最佳实践, 并考虑了各种极端情况. ...

2015-12-23 · 3 min · 613 words · -

Paxos

Paxos paxos Paxos (Greek: Παξοί, pronounced Paksi in English ) 又名Paxi是希腊西南部一个风景如画的小岛。而Paxos算法则是现在很火的分布式一致性算法,为何以一个希腊小岛名字算法?Lamport这样解释道: I thought, and still think, that Paxos is an important algorithm. Inspired by my success at popularizing the consensus problem by describing it with Byzantine generals, I decided to cast the algorithm in terms of a parliament on an ancient Greek island. Leo Guibas suggested the name Paxos for the island. 为描述 Paxos 算法,Lamport 虚拟了一个叫做 Paxos 的希腊城邦,这个岛按照议会民主制的政治模式制订法律,但是没有人愿意将自己的全部时间和精力放在这种事情上。所以无论是议员,议长或者传递纸条的服务员都不能承诺别人需要时一定会出现,也无法承诺批准决议或者传递消息的时间。但是这里假设没有拜占庭将军问题 (Byzantine failure,即虽然有可能一个消息被传递了两次,但是绝对不会出现错误的消息) ;只要等待足够的时间,消息就会被传到。另外,Paxos 岛上的议员是不会反对其他议员提出的决议的[1]。 ...

2015-12-23 · 1 min · 99 words · -

Zookeeper

Zookeeper ZooKeeper 是 Hadoop 的一个子项目,一般用来管理较大规模、结构复杂的服务器集群,具有自己的配置文件语法、管理工具和部署模式 分布式的K/V存储 分布式协调系统 微服务注册中心 服务发现 zookeeper 起源于 Hadoop 生态系统 zookeeper 使用 ZAB 协议作为其一致性协议 znode 只能存1M以内的数据 写入性能低, 为保证一致性, 每次需要n/2+1的写入完成才算完成 zookeeper 的数据是全部存储在内存, 只适合存元数据 Zookeeper 的使用场景是有高一致性的 集群模式 Zookeeper 不仅可以单机提供服务,同时也支持多机组成集群来提供服务。实际上 Zookeeper 还支持另外一种伪集群的方式,也就是可以在一台物理机上运行多个 Zookeeper 实例,下面将介绍集群模式的安装和配置。 Zookeeper 的集群模式的安装和配置也不是很复杂,所要做的就是增加几个配置项。集群模式除了上面的三个配置项还要增加下面几个配置项: initLimit=5 syncLimit=2 server.1=192.168.211.1:2888:3888 server.2=192.168.211.2:2888:3888 initLimit: 这个配置项是用来配置 Zookeeper 接受客户端 (这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器) 初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 10 个心跳的时间 (也就是 tickTime) 长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5_2000=10 秒 syncLimit: 这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 2_2000=4 秒 ...

2015-12-23 · 4 min · 678 words · -

Java cpu 占用调查

Java cpu 占用调查 获取Java进程的PID jcmd -l 查看某一个进程的哪个线程占用 CPU 过高 top -H -p <PID> ps -mp <PID> -o THREAD,tid,time | sort -rn | head -n 10 打印进程的堆栈信息 jcmd <PID> Thread.print > stack.txt # 或 jstack <PID> stack.txt 将线程的PID转换为16进制 echo "obase=16; PID" | bc printf "%x\n" 73658 在第二步导出的 stack.txt 中查找转换成为16进制的线程PID。找到对应的线程栈 分析负载高的线程栈都是什么业务操作。优化程序并处理问题。 SystemTap,LatencyTOP,vmstat, sar, iostat, top, tcpdump iftop, iptraf, ntop, tcpdump Java的JProfiler/TPTP/CodePro Profiler 性能调优攻略 https://coolshell.cn/articles/7490.html/embed#?secret=sGuaIXdcl5 https://www.linuxhot.com/java-cpu-used-high.html https://linux.cn/article-5633-1.html

2015-12-23 · 1 min · 64 words · -

MySQL 大表 优化

MySQL 大表 优化 作者: zhuqz 链接: https://www.zhihu.com/question/19719997/answer/81930332 来源: 知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 第一优化你的sql和索引; 第二加缓存,memcached,redis; 第三以上都做了后,还是慢,就做主从复制或主主复制,读写分离,可以在应用层做,效率高,也可以用三方工具,第三方工具推荐360的atlas,其它的要么效率不高,要么没人维护; 第四如果以上都做了还是慢,不要想着去做切分,MySQL自带分区表,先试试这个,对你的应用是透明的,无需更改代码,但是sql语句是需要针对分区表做优化的,sql条件中要带上分区条件的列,从而使查询定位到少量的分区上,否则就会扫描全部分区,另外分区表还有一些坑,在这里就不多说了; 第五如果以上都做了,那就先做垂直拆分,其实就是根据你模块的耦合度,将一个大的系统分为多个小的系统,也就是分布式系统; 第六才是水平切分,针对数据量大的表,这一步最麻烦,最能考验技术水平,要选择一个合理的sharding key,为了有好的查询效率,表结构也要改动,做一定的冗余,应用也要改,sql中尽量带sharding key,将数据定位到限定的表上去查,而不是扫描全部的表; MySQL数据库一般都是按照这个步骤去演化的,成本也是由低到高;有人也许要说第一步优化sql和索引这还用说吗?的确,大家都知道,但是很多情况下,这一步做的并不到位,甚至有的只做了根据sql去建索引,根本没对sql优化 (中枪了没?) ,除了最简单的增删改查外,想实现一个查询,可以写出很多种查询语句,不同的语句,根据你选择的引擎、表中数据的分布情况、索引情况、数据库优化策略、查询中的锁策略等因素,最终查询的效率相差很大;优化要从整体去考虑,有时你优化一条语句后,其它查询反而效率被降低了,所以要取一个平衡点;即使精通MySQL的话,除了纯技术面优化,还要根据业务面去优化sql语句,这样才能达到最优效果;你敢说你的sql和索引已经是最优了吗?再说一下不同引擎的优化,myisam读的效果好,写的效率差,这和它数据存储格式,索引的指针和锁的策略有关的,它的数据是顺序存储的 (innodb数据存储方式是聚簇索引) ,他的索引btree上的节点是一个指向数据物理位置的指针,所以查找起来很快, (innodb索引节点存的则是数据的主键,所以需要根据主键二次查找) ;myisam锁是表锁,只有读读之间是并发的,写写之间和读写之间 (读和插入之间是可以并发的,去设置concurrent_insert参数,定期执行表优化操作,更新操作就没有办法了) 是串行的,所以写起来慢,并且默认的写优先级比读优先级高,高到写操作来了后,可以马上插入到读操作前面去,如果批量写,会导致读请求饿死,所以要设置读写优先级或设置多少写操作后执行读操作的策略;myisam不要使用查询时间太长的sql,如果策略使用不当,也会导致写饿死,所以尽量去拆分查询效率低的sql,innodb一般都是行锁,这个一般指的是sql用到索引的时候,行锁是加在索引上的,不是加在数据记录上的,如果sql没有用到索引,仍然会锁定表,MySQL的读写之间是可以并发的,普通的select是不需要锁的,当查询的记录遇到锁时,用的是一致性的非锁定快照读,也就是根据数据库隔离级别策略,会去读被锁定行的快照,其它更新或加锁读语句用的是当前读,读取原始行;因为普通读与写不冲突,所以innodb不会出现读写饿死的情况,又因为在使用索引的时候用的是行锁,锁的粒度小,竞争相同锁的情况就少,就增加了并发处理,所以并发读写的效率还是很优秀的,问题在于索引查询后的根据主键的二次查找导致效率低;ps:很奇怪,为什innodb的索引叶子节点存的是主键而不是像mysism一样存数据的物理地址指针吗?如果存的是物理地址指针不就不需要二次查找了吗,这也是我开始的疑惑,根据mysism和innodb数据存储方式的差异去想,你就会明白了,我就不费口舌了!所以innodb为了避免二次查找可以使用索引覆盖技术,无法使用索引覆盖的,再延伸一下就是基于索引覆盖实现延迟关联;不知道什么是索引覆盖的,建议你无论如何都要弄清楚它是怎么回事!尽你所能去优化你的sql吧!说它成本低,却又是一项费时费力的活,需要在技术与业务都熟悉的情况下,用心去优化才能做到最优,优化后的效果也是立竿见影的!

2015-12-22 · 1 min · 27 words · -

netty tcp 参数

netty tcp 参数 TCP_NODELAY 这个选项的作用就是禁用 Nagle’s Algorithm NAGLE算法通过将缓冲区内的小封包自动相连,组成较大的封包,阻止大量小封包的发送阻塞网络,从而提高网络应用效率。但是对于时延敏感的应用场景需要关闭该优化算法; SO_RCVBUF 接收缓冲区 SO_SNDBUF 发送缓冲区 SO_KEEPALIVE 保持连接检测对方主机是否崩溃,避免 (服务器) 永远阻塞于TCP连接的输入。 设置该选项后, 如果2小时内在此 socket 的任一方向都没有数据交换, TCP就自动给对方发一个保持存活探测分节 (keepalive probe)。 SO_REUSEADDR SO_BACKLOG The backlog argument is the requested maximum number of pending connections on the socket. SO_RCVBUF ,SO_SNDBUF 每个TCP socket在内核中都有一个发送缓冲区和一个接收缓冲区,TCP的全双工的工作模式以及TCP的滑动窗口便是依赖于这两个独立的buffer以及此buffer的填充状态。接收缓冲区把数据缓存入内核,应用进程一直没有调用read进行读取的话,此数据会一直缓存在相应socket的接收缓冲区内。再啰嗦一点,不管进程是否读取socket,对端发来的数据都会经由内核接收并且缓存到socket的内核接收缓冲区之中。read所做的工作,就是把内核缓冲区中的数据拷贝到应用层用户的buffer里面,仅此而已。进程调用send发送的数据的时候,最简单情况 (也是一般情况) ,将数据拷贝进入socket的内核发送缓冲区之中,然后send便会在上层返回。换句话说,send返回之时,数据不一定会发送到对端去 (和write写文件有点类似) ,send仅仅是把应用层buffer的数据拷贝进socket的内核发送buffer中。后续我会专门用一篇文章介绍read和send所关联的内核动作。每个UDP socket都有一个接收缓冲区,没有发送缓冲区,从概念上来说就是只要有数据就发,不管对方是否可以正确接收,所以不缓冲,不需要发送缓冲区。 接收缓冲区被TCP和UDP用来缓存网络上来的数据,一直保存到应用进程读走为止。对于TCP,如果应用进程一直没有读取,buffer满了之后,发生的动作是: 通知对端TCP协议中的窗口关闭。这个便是滑动窗口的实现。保证TCP socket 接收缓冲区不会溢出,从而保证了TCP是可靠传输。因为对方不允许发出超过所通告窗口大小的数据。 这就是TCP的流量控制,如果对方无视窗口大小而发出了超过窗口大小的数据,则接收方TCP将丢弃它。 UDP: 当 socket 接收缓冲区满时,新来的数据报无法进入接收缓冲区,此数据报就被丢弃。UDP是没有流量控制的;快的发送者可以很容易地就淹没慢的接收者,导致接收方的UDP丢弃数据报。 以上便是TCP可靠,UDP不可靠的实现。 这两个选项就是来设置TCP连接的两个buffer尺寸的。 /** * 100 Continue * 是这样的一种情况: HTTP客户端程序有一个实体的主体部分要发送给服务器,但希望在发送之前查看下服务器是否会 * 接受这个实体,所以在发送实体之前先发送了一个携带100 * Continue的Expect请求首部的请求。服务器在收到这样的请求后,应该用 100 Continue或一条错误码来进行响应。 */ http://www.cnblogs.com/qq78292959/archive/2013/01/18/2865926.html ...

2015-12-19 · 1 min · 77 words · -

netty http client

netty http client http://www.cnblogs.com/luxiaoxun/p/3959450.html 基于Netty4的HttpServer和HttpClient的简单实现 Netty的主页: http://netty.io/index.html 使用的Netty的版本: netty-4.0.23.Final.tar.bz2 ‐ 15-Aug-2014 (Stable, Recommended) Http 消息格式: Http request: Method path-to-resource HTTPVersion-number Header-name-1: value1 Header-name-2: value2 Optional request body Http response: HTTP/Version-number response-code response-phrase Header-name-1: value1 Header-name-2: value2 Optional response body 实现一个简单的Http请求及响应过程: Client向Server发送http请求。 Server端对http请求进行解析。 Server端向client发送http响应。 Client对http响应进行解析。 Netty中Http request消息格式: Netty中Http response消息格式: 代码实例: Http Server: package com.netty.test; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; ...

2015-12-17 · 2 min · 380 words · -

AKKA

AKKA http://sunxiang0918.cn/2016/01/10/Akka-in-JAVA-1/ Akka是一个由Scala编写的,能兼容Sacala和JAVA的,用于编写高可用和高伸缩性的Actor模型框架.它基于了事件驱动的并发处理模式,性能非常的高,并且有很高的可用性.大大的简化了我们在应用系统中开发并发处理的过程.它在各个领域都有很好的表现. 使用AKKA的好处 就如上面简介中所说的,AKKA把并发操作的各种复杂的东西都统一的做了封装.我们主要关心的是业务逻辑的实现,只需要少量的关心Actor模型的串联即可构建出高可用,高性能,高扩展的应用. Akka for JAVA 由于AKKA是使用Scala编写的,而Scala是一种基于JVM的语言.因此JAVA对AKKA的支持也是很不错的.Akka自身又是采用微内核的方式来实现的,这就意味着能很容易的在自己的项目中应用AKKA,只需要引入几个akka的Lib包即可.而官方直接就提供了Maven库供我们在JAVA中使用AKKA. 这些AKKA的依赖包主要有: akka-actor:最核心的依赖包,里面实现了Actor模型的大部分东西 akka-agent:代理/整合了Scala中的一些STM特性 akka-camel:整合了Apache的Camel akka-cluster:akka集群依赖,封装了集群成员的管理和路由 akka-kernel:akka的一个极简化的应用服务器,可以脱离项目单独运行. akka-osgi:对OSGI容器的支持,有akka的最基本的Bundle akka-remote:akka远程调用 akka-slf4j:Akka的日志事件监听 akka-testkit:Akka的各种测试工具 akka-zeromq:整合ZeroMQ 其中最总要的就是akka-actor,最简单的AKKA使用的话,只需要引入这个包就可以了. Actor 模型 什么是Actor 既然说AKKA是一个Actor模型框架,那么就需要搞清楚什么是Actor模型.Actor模型是由Carl Hewitt于上世纪70年代提出的,目的是为了解决分布式编程中的一系列问题而产生. 在Actor模型中,一切都可以抽象为Actor. 而Actor是封装了状态和行为的对象,他们的唯一通讯方式就是交换消息,交换的消息放在接收方的邮箱(Inbox)里.也就是说Actor之间并不直接通信,而是通过了消息来相互沟通,每一个Actor都把它要做的事情都封装在了它的内部. 每一个Actor是可以有状态也可以是无状态的,理论上来讲,每一个Actor都拥有属于自己的轻量级进程,保护它不会被系统中的其他部分影响.因此,我们在编写Actor时,就不用担心并发的问题. 通过Actor能够简化锁以及线程管理,Actor具有以下的特性: 提供了一种高级的抽象,能够封装状态和操作.简化并发应用的开发. 提供了异步的非阻塞的/高性能的事件驱动模型 超级轻量级的线程事件处理能力. 要在JAVA中实现一个Actor也非常的简单,直接继承akka.actor.UntypedActor类,然后实现public void onReceive(Object message) throws Exception方法即可. https://guobinhit.github.io/akka-guide/ https://www.zhihu.com/question/279512440/answer/407373037

2015-12-15 · 1 min · 41 words · -

MySQL Innodb 锁

MySQL Innodb 锁 InnoDB 发音为"in-no-db" 行锁 行锁的分类 行锁从mode上分为X、S,type上进一步细分为以下类型: LOCK_GAP: GAP 锁, 锁两个记录之间的GAP, 防止记录插入; LOCK_ORDINARY: 官方文档中称为 “Next-Key Lock” ,锁一条记录及其之前的间隙,这是RR级别用的最多的锁,从名字也能看出来; LOCK_REC_NOT_GAP: 只锁记录; LOCK_INSERT_INTENSION: 插入意向GAP锁,插入记录时使用,是LOCK_GAP的一种特例。 RC级别只有记录锁,没有 Next-Key Lock 和 GAP锁,因此存在幻读现象。 行锁是加在记录上的锁,InnoDB中的记录是以B+树索引的方式组织在一起的,InnoDB的行锁实际是 index record lock,即对B+索引叶子节点的锁。索引可能有多个,因此操作一行数据时,有可能会加多个行锁在不同的B+树上。 在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足。 在数据库的锁机制中介绍过,在DBMS中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎)、表级锁(MYISAM引擎)和页级锁(BDB引擎 )。 行级锁 行级锁 是 MySQL 中锁定粒度最细的一种锁, 表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小, 但加锁的开销也最大。行级锁分为共享锁和排他锁 行级锁特点 开销大, 加锁慢;会出现死锁;锁定粒度最小, 发生锁冲突的概率最低, 并发度也最高。 表级锁 表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。表级锁定分为**表共享读锁 (共享锁)与表独占写锁 (排他锁)**。 表级锁特点 开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。 页级锁 页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。BDB支持页级锁 页级锁特点 开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般 MySQL常用存储引擎的锁机制 MyISAM和MEMORY采用表级锁(table-level locking) BDB采用页面锁(page-level locking)或表级锁,默认为页面锁 InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁 Innodb中的行锁与表锁 前面提到过,在Innodb引擎中既支持行锁也支持表锁,那么什么时候会锁住整张表,什么时候或只锁住一行呢? InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着: 只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁! 在实际应用中,要特别注意InnoDB行锁的这一特性,不然的话,可能导致大量的锁冲突,从而影响并发性能。 在不通过索引条件查询的时候,InnoDB 确实使用的是表锁,而不是行锁。 由于 MySQL 的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行 的记录,但是如果是使用相同的索引键,是会出现锁冲突的。应用设计的时候要注意这一点。 当表有多个索引的时候,不同的事务可以使用不同的索引锁定不同的行,另外,不论 是使用主键索引、唯一索引或普通索引,InnoDB 都会使用行锁来对数据加锁。 即便在条件中使用了索引字段,但是否使用索引来检索数据是由 MySQL 通过判断不同 执行计划的代价来决定的,如果 MySQL 认为全表扫 效率更高,比如对一些很小的表,它 就不会使用索引,这种情况下 InnoDB 将使用表锁,而不是行锁。因此,在分析锁冲突时, 别忘了检查 SQL 的执行计划,以确认是否真正使用了索引。 行级锁与死锁 MyISAM中是不会产生死锁的,因为MyISAM总是一次性获得所需的全部锁,要么全部满足,要么全部等待。而在InnoDB中,锁是逐步获得的,就造成了死锁的可能。 ...

2015-12-15 · 3 min · 637 words · -

jcl-over-slf4j

http://www.cnblogs.com/zcy_soft/p/3566208.html jcl-over-slf4j log桥接工具简介 java 界里有许多实现日志功能的工具,最早得到广泛使用的是 log4j,许多应用程序的日志部分都交给了 log4j,不过作为组件开发者,他们希望自己的组件不要紧紧依赖某一个工具,毕竟在同一个时候还有很多其他很多日志工具,假如一个应用程序用到了两个组件,恰好两个组件使用不同的日志工具,那么应用程序就会有两份日志输出了。 为了解决这个问题,Apache Commons Logging (之前叫 Jakarta Commons Logging,JCL) 粉墨登场,JCL 只提供 log 接口,具体的实现则在运行时动态寻找。这样一来组件开发者只需要针对 JCL 接口开发,而调用组件的应用程序则可以在运行时搭配自己喜好的日志实践工具。 所以即使到现在你仍会看到很多程序应用 JCL + log4j 这种搭配,不过当程序规模越来越庞大时,JCL的动态绑定并不是总能成功,具体原因大家可以 Google 一下,这里就不再赘述了。解决方法之一就是在程序部署时静态绑定指定的日志工具,这就是 SLF4J 产生的原因。 跟 JCL 一样,SLF4J 也是只提供 log 接口,具体的实现是在打包应用程序时所放入的绑定器 (名字为 slf4j-XXX-version.jar) 来决定,XXX 可以是 log4j12, jdk14, jcl, nop 等,他们实现了跟具体日志工具 (比如 log4j) 的绑定及代理工作。举个例子: 如果一个程序希望用 log4j 日志工具,那么程序只需针对 slf4j-api 接口编程,然后在打包时再放入 slf4j-log4j12-version.jar 和 log4j.jar 就可以了。 现在还有一个问题,假如你正在开发应用程序所调用的组件当中已经使用了 JCL 的,还有一些组建可能直接调用了 java.util.logging,这时你需要一个桥接器 (名字为 XXX-over-slf4j.jar) 把他们的日志输出重定向到 SLF4J,所谓的桥接器就是一个假的日志实现工具,比如当你把 jcl-over-slf4j.jar 放到 CLASS_PATH 时,即使某个组件原本是通过 JCL 输出日志的,现在却会被 jcl-over-slf4j “骗到"SLF4J 里,然后 SLF4J 又会根据绑定器把日志交给具体的日志实现工具。过程如下 ...

2015-12-09 · 1 min · 129 words · -

脑裂问题

脑裂问题 http://my.oschina.net/moooofly/blog/92288?fromerr=sduNT5ao 在心跳失效的时候,就发生了脑裂 (split-brain) 。 ( 一种常见的脑裂情况可以描述如下) 比如正常情况下, (集群中的) NodeA 和 NodeB 会通过心跳检测以确认对方存在,在通过心跳检测确认不到对方存在时,就接管对应的 (共享) resource 。如果突然间,NodeA 和 NodeB 之间的心跳不存在了 (如网络断开) ,而 NodeA 和 NodeB 事实上却都处于 Active 状态,此时 NodeA 要接管 NodeB 的 resource ,同时 NodeB 要接管 NodeA 的 resource ,这时就是脑裂 (split-brain) 。 脑裂 (split-brain) 会 引起数据的不完整性 ,并且可能会 对服务造成严重影响 。 引起数据的不完整性主要是指,集群中节点 (在脑裂期间) 同时访问同一共享资源,而此时并没有锁机制来控制针对该数据访问 (都脑裂了,咋控制哩) ,那么就存在数据的不完整性的可能。 对服务造成严重影响,举例来说,可能你早上上班的时候会发现 NodeA 和 NodeB 同时接管了一个虚拟 IP 。 所以,裂脑这个词是一个很形象的术语,用于描述 HA 系统危机的情景。 曾经看央视 10 套教育频道,获知"裂脑"是治疗"癫痫"病的一种手术。医生们认为癫痫病发作是由于大脑"异常放电"所至。为了阻止"异常放电"波及整个大脑 (左、右半脑) ,就用手术来割断病人左右脑的连接神经。使今后病人在发病时至少还有半个大脑正常、能控制行为。但施行过手术的所谓"裂脑人"在术后有一段不适应期,表现得行为分裂,仿佛体内存在着2个人,时常要发生冲突。例如,右脑想让一只手去脸上挠痒痒,左脑却不认同、以为是谁的手要"登鼻子上脸"就让另一只手去阻止,于是明明是自己的 2 只手,却互不相让、扭在一起扳起了手腕…… 在"双机热备"高可用 (HA) 系统中,当联系 2 个节点的"心跳线"断开时,本来构成同一个整体、动作协调的 HA 系统,就分裂成为 2 个独立的个体。由于相互失去了联系,都以为是对方出了故障,2 个节点上的 HA 软件像"裂脑人"一样,“本能"地争抢"共享资源”、争着起动"应用服务",那么必然会发生严重的后果: 或者共享资源被瓜分、两边的"服务"都起不来了;或者两边"服务"都起来了,但同时读写"共享存储",导致数据损坏 (常见如数据库轮询着的联机日志出错) 。 ...

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

archlinux kvm qemu gentoo

archlinux kvm qemu gentoo pacman -Syu pacman -S qemu pacman -S qemu-launcher qemu-img create -f raw gentoo.img 20G qemu-img create -f qcow2 gentoo 20G exec qemu-system-x86_64 -enable-kvm -cpu host -cdrom install-amd64-minimal-20150924.iso -boot order=d -drive file=gentooVM.img,if=virtio -netdev user,id=vmnic,hostname=gentoovm -device virtio-net,netdev=vmnic -m 2048M -monitor stdio -name "Gentoo VM" pacman -S linux-atm pacman -S bridge-utils 在主机上创建桥 创建桥的原因是虚拟机间,虚拟机与主机间的互联 $ sudo brctl addbr br0 ip tuntap # start gentoo with sshd gentoo dosshd # or /etc/init.d/sshd start #prepare partition #mounting mount /dev/sda4 /mnt/gentoo mkdir /mnt/gentoo/boot mount /dev/sda2 /mnt/gentoo/boot chmod 1777 /mnt/gentoo/tmp #Downloading the stage tarball https://bbs.archlinux.org/viewtopic.php?id=164461 ...

2015-12-07 · 1 min · 93 words · -

float double NaN

float double NaN http://zranye.iteye.com/blog/1344880 http://blog.csdn.net/naruto_ahu/article/details/8805808 (注意,double中的NaN类似) 在帮助文档中,NaN是这样解释的 (double的,和float差不多) : <!- Generated by javadoc (build 1.6.0-beta2) on Mon Mar 19 18:22:44 CST 2007 -> public static final double NaN 保存 double 类型的 NaN 值的常量。它等于 Double.longBitsToDouble(0x7ff8000000000000L) 返回的值。 我是这样解释的 (理解不深,有错请不吝赐教) : NaN-Not-a-Number,其实是指一个不合理的实数,在合法却不合理的情况下避免你的程序出现Exception。 NaN什么也不是,如果理解成一个超越了float范围的常量 (或者double) ,那也是不对的,为什么?试试判断 (NaN==NaN) 吧,你会发现这返回了一个false。这在java底层是怎么做到的呢?最直接的方式是看java源代码咯。 /** A constant holding a Not-a-Number (NaN) value of type float. It is equivalent to the value returned by Float.intBitsToFloat(0x7fc00000). ...

2015-12-04 · 1 min · 79 words · -

connection=keep alive 和close

connection=keep alive 和close 浏览器和服务器在建立 http 连接的时候需要3次握手, 在高并发的环境下每一次建立连接都3次握手会消耗太多的服务资源, 这个本质上是由于http是无状态造成的.http1.0默认开启了 connection=close 模式意味着服务器和客户端都需要关闭TCP连接, 而客户端是通过判断连接关闭来判断响应是否都收到了。http1.1 默认开启connection=keep-alive模式 (长连接) ,主要为了解决浏览器内高并发的访问服务器资源,而且每次的访问都可以复用连接,从而提高响应速度。但是也需要注意,因为浏览器无法判断当前发送的二进制码流是否结束, 也就是所谓的粘包问题, 所以在 keep-alive 模式下, 服务器需要显示的返回Content-Length 用来根据码流的长度来判断一个完整的 response 是否结束。

2015-12-02 · 1 min · 22 words · -

redis set

redis set # 删除集合 del set_name_0 redis set 是string类型对象的无序集合,set不管存储多少对象,对存储对象的add,remove和test操作的时间复杂度是O(1)。set最多能包含 232 – 1 个member。 增加, sadd 语法: sadd key member[member…] 解释: 对特定key的set增加一个或多个值,返回是增加元素的个数。注意: 对同一个member多次add,set中只会保留一份。 查询 smembers, sismember, scard, srandmember smembers 语法: smembers key 解释: 获取set中的所有member sismember 语法: sismember key member 解释: 判断值是否是set的member。如果值是set的member返回1,否则,返回0 scard 语法: scard key 解释: 返回set的member个数,如果set不存在,返回0 srandmember 语法: srandmember key 解释: 从set中返回一个随机member 删除 spop 语法: spop key 解释: 移除并返回一个随机member srem 语法: srem key member [member …] 解释: 移除一个或多个member smove 语法: smove source destination member ...

2015-12-01 · 1 min · 156 words · -