月度归档:2015年10月

nginx与tomcat之间的keep-alive配置

今天碰到的一个情况,tomcat与前端nginx之间的存在大量的TIME_WAIT状态的连接,第一反应是这里可能没有配置keep-alive。问ops,回复说启用了;要来nginx的配置看了一下,发现upstream里设置了keepalive参数:

upstream  tomcat {
    server x.x.x.x:8080;
    ...
    keepalive 16;
}

不确定这个参数是不是http的keep-alive,在nginx的网站上找了一下

Syntax: keepalive connections;
Default:    —
Context:    upstream

The connections parameter sets the maximum number of idle keepalive connections to upstream servers that are preserved in the cache of each worker process.

它并不是与后端节点开启http-alive方式的意思,nginx作为反向代理后端并不局限http协议,这里的keepalive设置相当于每个worker连接池的最大空闲keepalive连接数,跟http里的keep-alive不是一回事。

在官方文档里明确要对后端节点使用http keep-alive 可以指定http版本为1.1:

location /http/ {
    proxy_pass http://http_backend;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    ...
}

或者仍使用http 1.0协议,但显式的设置http header里Connection参数为Keep-Alive,这是因为keep-alive是http1.1的默认特性,在1.0里最初并未实现是后来从1.1里backport到1.0的,需要显式设定这个参数才启用:

location /http/ {
    proxy_pass http://http_backend;
    proxy_http_version 1.0;
    proxy_set_header Connection "Keep-Alive";
    ...
}

为了确认有效性,可以对tomcat的logger增加一句

org.apache.coyote.http11.level = FINE

这样可以在tomcat日志里看到每个请求的http header信息:

FINE: Received [GET / HTTP/1.0
Connection: Keep-Alive
Host: localhost:8080
User-Agent: curl/7.37.1
Accept: */*

确实在header里增加了。建议还是配置为http 1.1协议,支持chunked等特性。

ps, keepalive 这个词可能是指连接池或者tcp层面的参数,要看上下文。在http里是keep-alive,注意中间有个连字符。

bash debug

便于调试bash的输出效果:

#!/usr/bin/env bash

if [ -z "$1" ];then
  echo "usage: bashdebug your_script"
  exit 1
fi

PS4='+[$(date "+%Y-%m-%d %H:%M:%S") +${SECONDS}s ${BASH_SOURCE} ${LINENO}] ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'

ACK=""
which ack &>/dev/null
[ $? -eq 0 ] && ACK=$(which ack)

if [ -z "$ACK" ];then
  bash -x $1
else
  bash -x $1 |& $ACK --passthru "^\+.*:"
fi

Java/Scala程序员书单

这里列一些对Java/Scala程序员有帮助的书单,先随意记录一些,后续有空会分类一下并补充更多的评价。

《软件框架设计的艺术》
这是Netbeans的创始人写的一本很有价值的书,里面的边角细节也很有料。国内市场上没有对这本书给予应给的赞誉。

《Effective Java 第二版》
被称为Java领域的圣经,小中见大。探讨的不仅仅是Java语言,也包括一些形而上的东西,取决于读的人理解多少。我在面试时喜欢考察一些基础的东西,以及背后的想法和初衷,可惜相当多的程序员这本书都没仔细阅读过。

《并发编程实践》

《Java并发编程》

《Java 并发编程设计原则与模式》

《代码的未来》

《Programming in Scala》
中文版是”Scala编程”,对scala程序员来说这本书你不能不读

《Java解惑》

《深入Java虚拟机》(原书第2版)
有些过时了

《Java与模式》
十几年前正是模式刚流行的时候,阎宏博士的这本书当时在中文圈里引起了很大反响,这本书算得上一本经典巨著。

《观止-微软创建NT和未来的夺命狂奔》
好些年前从温绍锦那儿借来看的,忘了还给他。介绍了NT的开发过程,写给大众看的,偏故事性,读起来很过瘾。

《程序设计语言》第三版

《重构》

《Java Rules中文版》

《企业应用架构模式》

《领域驱动设计》

《Java虚拟机规范(Java SE 7版)》

《Java程序员修炼之道》

《HTTP权威指南》

《TCP/IP详解卷1:协议》

《TCP/IP详解卷2:实现》

《构建高性能Web站点》

《JAVASCRIPT语言精髓与编程实践》

《深入剖析Tomcat》

《Maven实战》

《哥德尔、艾舍尔、巴赫:集异璧之大成》

《An Introduction to Functional Programming Through Lambda Calculus》

《分布式系统概念与设计(原书第3版)》

《实用Common Lisp编程》

《面向模式的软件架构 卷1:模式系统》

《面向模式的软件架构 卷2:并发和联网对象模式》

《面向模式的软件架构 卷3:资源管理模式》

《面向模式的软件架构 卷4:分布式计算的模式语言》

《面向模式的软件架构 卷5:模式与模式语言》

《编程语言实现模式》

《架构之美》

《精通正则表达式》

《浪潮之巅》

《多处理器编程的艺术》

《JAVA核心技术卷II:高级特性》

《Java核心技术 卷I: 基础知识》

《程序员修炼之道——从小工到专家》

maven的仲裁

模块化的问题是无法避免的一个问题。对创业公司来说,在团队和产品在发展到一定程度之前,靠自我约束。

这里有一个案例是项目里依赖了b组件,b组件依赖了a组件1.0.2版本,而用户也直接在pom依赖了a组件并声明的1.0.0版本,结果在仲裁时选择了1.0.0版本的a组件:

 +- com.xxx:a:jar:1.0.0:compile
 |   
 +- ...
 |  +- ...
 |  
 +- com.xxx:b:jar:1.0.0:compile
 |  |  
 |  +- (com.xxx:a:jar:1.0.2:compile - omitted for duplicate)

对于依赖某个组件的多个版本,maven的仲裁过程,并不是简单的使用高版本,而是根据从根节点到各个组件节点之间的路径深度,路径短的组件优先,如果路径深度相同,则是先发现的那个。类似一棵树的广度遍历。

sh script.sh与./script.sh的差异

这两种方式差异是进程名称的不同,假设有以下内容的脚本:

$ cat script.sh
#!/bin/bash
sleep 4400

sh script.sh执行,它是明确的启动一个sh命令,把脚本名称做参数传递给它,进程名称是sh:

$ pstree  
 ...
 |-sshd-+...
 |      |-sshd---sshd---bash---sh---sleep

而以./script.sh方式执行,操作系统负责脚本加载(execve系统调用),进程名称是脚本名

$ pstree  
 ...
 |-sshd-+...
 |      |-sshd---sshd---bash---script.sh---sleep