Category: Programming

  • 非阻塞IO与异步IO

    本文是自己对最近学习到的IO相关知识的一点整理,之后会逐渐增加。 首先非阻塞IO(non-blocking IO)相信很多人都听说过,比如Nginx,Redis,NodeJS等等。得到的印象大多是非阻塞IO比传统IO(blocking IO)要好。这里多少有点误解。 非阻塞IO的目的是高并发,比如C10K这种目标。在连接数不高的时候性能并不会比传统IO好。为什么传统IO难以做到C10K,主要原因还是可以建立的进程/线程数量有限,以及高并发情况下IO等待时间太多,阻塞进程/线程运行等原因。 当然非阻塞IO并不是完全非阻塞的,IO通常分为数据等待和数据从内核空间拷贝到用户空间的两部分,传统IO(阻塞IO)在这两个步骤都会阻塞,但是非阻塞IO只在数据拷贝的时候阻塞,数据等待时系统通常会返回一个特定的异常码来提示数据未准备好。 非阻塞IO是一个行为特征,具体实现有select/poll,Linux 2.6之后的epoll等IO多路复用的系统调用。直观上来讲,非阻塞IO和IO多路复用没有关系,但是如果你一直在某个fd(文件描述符)上轮询的话,就会变得和传统IO没有区别,所以一般都是在多个fd上等待,当其中某个数据就绪了再取数据,这样就可以体现在非阻塞IO在数据等待这一步非阻塞的优势了。 从编程语言来说,非阻塞也可以选择用注册callback异步调用来实现。实际的IO类型中也有异步IO,但是大部分人都不怎么谈到异步IO,说非阻塞IO其实就是指epoll,其原因之一是Linux上AIO(异步IO)实现差强人意,Windows上IO多路复用只有select,剩下的就是异步IO,即IOCP,Windows貌似希望开发人员使用IOCP而不是开发类似epoll在Windows上的实现。服务器端开发,你懂的,Windows的用武之地很少。 IO多路复用为什么epoll脱颖而出,主要还是他的数据通知机制。select虽然大部分平台都支持,但是fd有数量限制,1024个。poll消除了这个限制,但是得到数据就绪的响应之后,你必须遍历庞大的fd列表来得到就绪的fd。epoll的优势在于返回的响应中包含数据就绪的fd,综合各方面来说是最优的。 当然epoll是Linux的系统调用,如果在Windows上你只能用select,在Solaris上你需要/dev/poll,OS X是kqueue,通常编程语言会帮你统一API,比如Java。但是关于非阻塞IO的基本知识建议还是要了解一下。 参考: https://segmentfault.com/a/1190000003063859?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io#articleHeader12 http://blog.omega-prime.co.uk/?p=155 http://www.kegel.com/c10k.html

  • [java]apache httpclient timeout waiting for connection

    本文是公司内一个问题的分析记录。涉及的框架为apache的commons-httpclient 3.x。 问题特征 无法从连接池中获取连接,异常描述为timeout waiting for connection netstat看到连接状态为CLOSE_WAIT 目标服务器ping得通,甚至curl等方式亦可以获取结果

  • sinatra/activerecord/grape小试

    以下是最近今天学习sinatra等框架的使用笔记。 sinatra 参考文档 http://www.sinatrarb.com/intro.html 个人感觉类似Spring MVC,主要学习了 URL映射 参数 静态文件 模板处理(ERB) 变量传递

  • [DSL]模式匹配与请求跳转

    [DSL]模式匹配与请求跳转

    具体上次撰写博客有一段时间了。这段时间内自己学些了很多,想了很多,尝试去理解了很多。结果之一是不管这个博客是为了什么而建立的,我还是把自己的技术思考记录下来。 本文描述是自己在工作中实现的一种DSL。DSL是个人今天年初左右才决定的发展方向,只是在具体工作中使用还是第一次。希望这可以作为自己在技术上选择性发展的一个好的开端。 由于是工作中开发出来的一种DSL,所以不会讲太具体的业务场景,而是以技术设计与实现为主。 本DSL的设计目的的核心如题,模式匹配和请求跳转。结合起来就是按照某种业务规则以模式匹配的方式决定请求是否跳转。更直接的一种表达方式是if else决定是否要redirect,只是这段if else是用DSL定义的。 使用DSL定义规则的好处在于更清晰地展现跳转的条件,避免技术实现给业务规则辨识带来的”噪音”,特别是复杂的跳转规则。其次是快速支持规则的变化,比如易变(不管是运行时易变,还是需求期易变)的规则,附带的另外一个好处是如果业务上需要动态定义的话,DSL可以快速支持,不再需要通过数据库设计,配置等传统方式。

  • [Java]运行时动态改变日志级别

    其实这不是什么神奇的trick,只是很多人包括我在一直以来使用Java的日志框架比如log4j时没有意识到可以动态改变日志级别。如果你看到别人这么写了的话,很快就会转变观念的,我也是。 https://github.com/xnnyygn/dynamic-log-level 这个github是我整理的log4j动态改变日志级别的代码以及测试,有兴趣的可以参考下。 个人觉得这个trick可以用的地方还是程序员给自己开“后门”,特别是查线上问题时。由于很多人打印日志的级别的convention不一致。比如我喜欢非常详细的输入参数和输出结果用DEBUG,但是有些人就喜欢打INFO。一些复杂的逻辑有些人打了十几八行的INFO级别日志,看得我心烦,这帮人打INFO就像喝水一样……所以有些时候临时改变日志级别可能是有用的。不过从开发上来说,没有很好地统一日志级别规范,没有重视CR,是导致这个问题的主因,但是作为程序员要给自己留一手,比如动态改变日志级别之类的。

  • [Java]简单的延迟初始化实现

    本篇文章本来打算在上个月下半旬写的,不过个人状态一直都不太好,最近重新开始调整自己的技术心态,慢慢恢复,这篇也算是恢复中的一小步吧。 延迟初始化是我在上个月公司的一个项目中加入的一个技术,感觉小组对这种东西不感兴趣,所以还是放到自己的博客上来了。技术背景是业务对象是一个非常大的对象(胖领域模型),每次加载非常耗时,而且因为部分非关键服务的不稳定导致不需要这些服务数据的功能不可用。举个例子,导航页不需要用户的B信息,但是每次加载用户信息由于是在服务层(是的,传统的分层结构)加载的,无法直接控制加载的内容,所以导致在B服务失败之后,导航页不可用。 从技术角度来说,领域模型完全是保证业务执行的必要条件,但是实际情况并不是所有场景都需要这么严格的领域模型完整性的保证的,所以类似“降级”的处理方式应由而生。具体来说就是“按需加载”。实现“按需加载”的方式不仅仅只有延迟初始化一种,通过服务的参数显示地控制加载的内容也是一种方式,不过存在侵入性和严格的规约,对开发来说并不是那么方便。其实“按需加载”不是只在特定业务场景才有的需求,在ORM上,加载关联数据也是一种典型的“按需加载”。所以亦可以参考ORM在“按需加载”方面的实现。 在讲我的简化版延迟初始化之前,先大致讲下Hibernate这个ORM在按需加载上的处理。Hibernate主要支持one-to-one和one-to-many下的按需加载,Hibernate 3开始支持部分字段的按需加载(CLOB和BLOB不算在内,3之前就有支持)。实现上,部分字段的加载需要bytecode替换,one-to-many是通过改写集合的处理,one-to-one是通过代理对象,具体来说是CGLIB,因为JDK动态代理对象只支持接口。 了解这些对于我的实现有所帮助,不过除了one-to-many很快就能模仿写之外,部分字段的延迟初始化和one-to-one的处理都比较麻烦。one-to-one在查到结果为null时会比较麻烦,从调用上看应该是代理整个领域模型而不是单个延迟加载的对象,这块个人没有细究,因为我后来想想我不需要非常严格的模型字段规约,小小地修改模型理论上也不会有太大问题。而且部分字段的延迟初始化不是类似单个延迟初始化对象就可以解决的。

  • scala99解题小结(List)

    一个月之前,我把之前知道的scala99除了最后两题都做了下。总体来说自己用Scala来解决一些算法问题上有了一些感觉。 scala99的问题分为List,Arithmetic,Logic,Binary Tree,Multiway Tree,Graph和Misc。树和图和之后的问题和算法关系大一些。以下列一些影像比较深的题目。 本次先是List相关。

  • 用DLX解sudoku(数独)

    最近在做scala99,其中有一道题目P97是sudoku(数独)。一开始我想到的是列举每个空格的可选数字,选择可选数字最少的的格子开始填写。每次填写,修改关联格子的可选数字。再次尝试填写。这里无解条件是存在没有可选数字的格子。还有就是easy或者normal级别的数独一般可选数字都是1个,分批填写很快就能完成。hard或以上就没有那么幸运了,必须猜测然后验证,存在回溯。 这里描述的算法其实就是搜索+启发。启发是选择性地从最少可选数的格子开始。猜测+验证,感觉这个问题属于NP问题。事实上也确实是,而且可以转化为NP完全的精确覆盖问题(Exact Cover),所以这个问题也是NP完全问题。 P97给的答案有两个,第一个就是搜索+启发,第二个是DLX。DLX是Exact Cover的高效解法。本文就是讲如何用DLX来解数独问题的。考虑到scala99上第二个实现大部分都是可变数据,所以我用Java实现了相应算法。

  • finagle简单使用

    在看awseome-scala的时候,正好看到了twitter的finagle。自己公司里貌似也有那种关注load balance等的解决方案,不过不是很容易理解。考虑到自己之前几个月都在弄电子技术了,重新弄点网络相关的把。 这次的任务是做了一个thrift+finagle的远程服务调用例子。其实不是很难,如果不是连续碰到finagle的坑的话。finagle是twitter开源出来的一个分布式系统解决方案,毕竟是大公司出来的东西,更新频率特别是文档很低,很多文档基本都是几年前,好在有代码……

  • rabbitmq在scala下的使用尝试

    最近重拾scala,由于某些原因想要尝试了rabbitmq。于是便有了这块代码。 刚才重新看了rabbitmq的官网,上面关于scala的客户端的信息貌似更新了?之前那个lift-amqp太旧了,没法使用。不过没关系,这篇就当做了记录下如何在scala的环境下用rabbitmq的Java客户端。如果你想直接用现成的scala客户端,可以参考这里。 首先你要安装rabbitmq,这样之后好测试。mac下用brew安装命令是 $ brew update $ brew install rabbitmq