Awesome Sysadmin

https://github.com/kahun/awesome-sysadmin

系统管理员的开源资源,资源暴多,技术选型时参考.

Tengine

http://dmsimard.com/2014/06/21/a-use-case-of-tengine-a-drop-in-replacement-and-fork-of-nginx/

使用tengine来做LB,通过Tengine的unbuffered requests特性实现了上传性能提升.

不过我自己装tengine启动就遇到了问题.

the configuration file //Users/bohr/software/tengine/conf/nginx.conf syntax is ok
nginx: [emerg] mkdir() "//Users/bohr/software/tengine/logs/access.log" failed (21: Is a directory)
configuration file //Users/bohr/software/tengine/conf/nginx.conf test failed

服务器操作系统应该选择 Debian/Ubuntu 还是 CentOS?

http://www.zhihu.com/question/19599986

生产环境选择操作系统还是要慎重.现在我厂在线上用ubuntu,遇到过几次诡异事件(服务器无缘无故挂了,没有任何日志,时间跳变),看了这篇文章,SA应该会把线上的linux服务器统一了吧.

web-starter-kit

https://github.com/google/web-starter-kit

Web Starter Kit is a starting point for multi-screen web development. It encompasses opinionated recommendations on boilerplate and tooling for building an experience that works great across multiple devices.

微服务:分解应用以实现可部署性和可扩展性

http://www.infoq.com/cn/articles/microservices-intro http://microservices.io/index.html

文章讨论了整体架构和微服务构架的优缺点.对于大型应用而言,微服务架构当然是首选.

API网关模式用于解耦应用客户端和微服务.我们可能没有考虑对不同的客户端提供不同粒度的服务(不同客户端的网络环境不一样).

对于非强一致性数据要求的场景,事件驱动的异步更新(服务发布事件声明有些数据发生了变化,其他的服务订阅这些事件并更新它们的数据)解耦了事件的生产者和消费者,简化了开发也提升了可用性.某应用,很多配置数据都存在memcache中,一笔业务需要查询缓存>5次,每次都要去查,感觉很不爽.还是使用本地缓存+事件驱动的异步更新来做比较好.

面向GC的Java编程

http://coolshell.cn/articles/11541.html

好文,总结的很不错.

spring boot Initializr

http://start.spring.io/

有了这个,创建spring boot项目就快了.

OOM Killer

很早听说OOM Killer这个东东,感觉很神秘.而且以前分析某次线上故障,我得出的结论是OOM Killer,但是没有找到日志,囧!最近在玩vagrant,用的ubuntu box,虚拟机内存分配512m,某应用配置jvm内存-Xms256M -Xmx512m -XX:PermSize=64m -XX:MaxPermSize=256m.应用在启动过程中日志刷了一会儿就不动了,command+c结束后,console报出:

INFO: Initializing Spring root WebApplicationContext
^C./tomcat.sh: line 6:  7649 Killed                  nohup mvn clean tomcat7:run -Dspring.profiles.active=$env -Dsys.name=$sysname > "$logfile" 2>&1 < /dev/null

找了很久,在/var/log/syslog发现如下日志:

May 22 09:47:41 vagrant-ubuntu-saucy-64 kernel: [ 5499.448534] Out of memory: Kill process 7649 (java) score 788 or sacrifice child
May 22 09:47:41 vagrant-ubuntu-saucy-64 kernel: [ 5499.449012] Killed process 7649 (java) total-vm:1460964kB, anon-rss:407220kB, file-rss:0kB

这篇文章解释如何处理oom

vagrant

https://github.com/astaxie/Go-in-Action/blob/master/ebook/zh/01.2.md

http://blog.segmentfault.com/fenbox/1190000000264347

http://docs.vagrantup.com/v2/getting-started/index.html

如果mac环境下虚拟机出现Failed to load VMMR0.r0 (VERR_SUPLIB_WORLD_WRITABLE),执行sudo chmod o-w /Applications再试试.

构建高可用系统的常用招数

http://bluedavy.me/?p=468

大牛的总结,分享+总结下:

  1. 监控和报警
监控和报警能提前发现问题/缩短故障时间,前提是得能正确的评估监控点.
  1. SPoF(Single Point of Failure)
单点故障也分层次的,不过我们coder一般只关注服务层面.服务尽量做到无状态,只需要做负载就ok了.不能做成无状态的就需要做集群了.实在不行的就做成主备.
  1. 解耦

    后端业务通过消息/事件来解耦(Eventbus也不错),前端页面模块化,互相不影响.

  2. 隔离

    隔离既要防止依赖的系统之间相互影响(防止故障传播),也要防止同一节点上的不同服务相互影响(资源隔离).

    宏观层面,区分服务重要性,如果都能服务化就好做了.不同服务可以选择配置不同个数的服务节点.重要的,访问量大的就多加点节点.这需要监控系统能准确评估服务访问情况.

    微观层面,在服务内部,服务对外提供的能力一般通过线程池大小和请求队列长度来控制.在这里,大不一定就好,多也不定就好.

  3. 容灾

这里谈了几点:超时控制/非关键业务自动降级(用dubbo实现就很方便)/手动降级/自恢复能力(比如druid连接池)/自我保护能力

自己补充点,快速故障恢复能力(日志很重要)/避免人为故障(减少开发人员犯错误的机会)/简单可依赖(能简单做的就绝对不玩花哨)

Uses MySQL to store schema-less data

http://backchannel.org/blog/friendfeed-schemaless-mysql

如何用mysql来存储schema-less的数据,实现很简单.

数据表:

CREATE TABLE entities (
	added_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
	id BINARY(16) NOT NULL,
   	 	updated TIMESTAMP NOT NULL,
	body MEDIUMBLOB,
	UNIQUE KEY (id),
	KEY (updated)
) ENGINE=InnoDB;

假如内容是:

{
	"id": "71f0c4d2291844cca2df6f486e96e37c",
	"user_id": "f48b0440ca0c4f66991c4d5f6a078eaf",
	"feed_id": "f48b0440ca0c4f66991c4d5f6a078eaf",
	"title": "We just launched a new backend system for FriendFeed!",
	"link": "http://friendfeed.com/e/71f0c4d2-2918-44cc-a2df-6f486e96e37c",
	"published": 1235697046,
	"updated": 1235697046,
} 如果要给title建立索引,创建新表

CREATE TABLE index_title (
	title varchar(100) ,
	entity_id BINARY(16) NOT NULL UNIQUE,
   		PRIMARY KEY (user_id, entity_id)
) ENGINE=InnoDB;

查询的时候先从索引表查出entity_id,然后在去entities表查询详细数据.可以存储数据为text,方便数据库直接操作(必要性不是很大,text太占内存了),当然最好还是存储压缩后的二进制数据.不是经常改动的数据,应用层在加上一层cache.

索引可以异步建立,定时任务周期性的去找updated的新数据.

为什么tomcat应用三分钟还关不掉

这种问题一般是因为还有非deamon线程在容器关闭时没有正确的关闭导致的.可以在执行tomcat shutdown脚本后,jstack线程栈,看下还有哪些非deamon线程在执行.

应用使用线程持一定要记得关闭线程池,可以用spring提供的.

<bean id="taskExecutor"
      class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="10"/>
    <property name="keepAliveSeconds" value="200"/>
    <property name="maxPoolSize" value="50"/>
    <property name="queueCapacity" value="1000"/>
    <property name="awaitTerminationSeconds" value="60"/>
    <property name="waitForTasksToCompleteOnShutdown" value="true"/>
</bean> 注意最后面两个参数.

The New RBAC: Resource-Based Access Control

最近看看shiro的相关资料,看到这篇文章.以前也隐隐约约思考过权限控制,也感觉RBAC控制粒度太粗了.作者提到Explicit Access Control概念,通过资源来解耦角色,控制粒度更细.从权限的分配角度来说,这样使用也更方便,可以把权限分配到某个用户/某个组/某个角色.

当然,我们把资源的权限和角色一一对于,角色有层次关系并且可以继承,RBAC也可以胜任细粒度的权限控制.

传递依赖检查

我们通过maven插件org.apache.maven.plugins:maven-enforcer-plugin启用<requireUpperBoundDeps/> 来检查传递依赖是否高于直接依赖,如果传递依赖的版本比直接依赖的版本高,则打包失败.

<requireUpperBoundDeps/>解释如下:

IF:

	A-->B1-->C2

	A-->C1

	C2>C1

THEN:

	throw Exception;

我觉得这个检查很有必要,但是解析的范围太宽了.一个项目依赖了很多的开源组件,我们最好是限制这个检查只检查我们自己的jar包.

修改插件默认行为,在org.apache.maven.plugins.enforcer.RequireUpperBoundDeps$RequireUpperBoundDepsVisitor#containsConflicts中加入:

String key=  resolvedPair.constructKey();
if(key!=null && !key.startsWith("com.xxx")){//不检查groupId中包括非com.xxx开头的jar包
  		return false;
}	

demo

下面说下检查出来的提示信息分析,比如下面的情况:

Failed while enforcing RequireUpperBoundDeps. The error(s) are [
	Require upper bound dependencies error for xxx.interchange:interchange-facade-settle:1.0.0.20121009 paths to dependency are:
	+-xxx.ppm:ppm-integration:1.0.1.6
 	 		+-xxx.interchange:interchange-facade-settle:1.0.0.20121009
	and
	+-xxx.ppm:ppm-integration:1.0.1.6
 	 		+-xxx.core.payengine:payengine-facade:2.0.0.20140314
   	 			+-xxx.interchange:interchange-facade-settle:1.0.0.20121009 (managed) <-- xxx.interchange:interchange-facade-settle:1.3.0.20140303

第一个告诉我们ppm-integration–>interchange-facade-settle:1.0.0.20121009.

第二个告诉我们ppm-integration–>payengine-facade:2.0.0.20140314–>interchange-facade-settle:1.3.0.20140303

根据maven 最短路径优先原则,ppm-integration最终会依赖interchange-facade-settle:1.0.0.20121009.但是payengine-facade:2.0.0.20140314它依赖interchange-facade-settle:1.3.0.20140303.如果classpath中只有interchange-facade-settle:1.0.0.20121009,运行时payengine-facade就有可能报找不到类,找不到方法之类的错误.

遇到这样的场景,最好是修改我们项目的直接依赖,让ppm-integration–>interchange-facade-settle:1.3.0.20140303,然后测试下是否ok.