日期分页算法

吃瓜群众

作为吃瓜群众的陈达,一向觉得分页算法不难,瞧不起人家,直到最近才发现,分页算法也需要细致的考虑,做得不好是会出现问题滴。

Read More

用户用浏览器访问一个网站的时候背后的过程与步骤

『注:这是我一年前在知乎的回答,高赞,不知为何被知乎删了,故搬移至此』

假设你用一个全新的浏览器(第一次启动的那种),访问百度(http://www.baidu.com/),在你敲入网址并按下回车之后,将会发生以下神奇的事情:

浏览器先尝试从Host文件中获取www.baidu.com对应的IP地址,如果能取到当然万事大吉大家都能嗨,如果不能,就使用DNS协议来获取IP咯。

在DNS协议中,PC会向你的本地DNS服务器求助(一般是路由器),希望从本地DNS服务器那里得到百度的IP,得到就好,得不到还得向更高层次的DNS服务器求助,最终总能得到百度的IP。

得到百度的IP,下一步是使用TCP协议,建立TCP连接。

在TCP协议中,建立TCP需要与百度服务器握手三次,你先告诉服务器你要给服务器发东西(SYN),服务器应答你并告诉你它也要给你发东西(SYN、ACK),然后你应答服务器(ACK),总共来回了3次,称为3次握手。

不过,建立TCP连接有个前提(或者说给服务器发消息有个前提):你必须能成功地把消息发到服务器上。虽然已经知道IP,但并无啥用(比如说,你在广东,你知道北京的地理坐标经纬度就能到北京了?你得知道有哪些路通往北京吧你得准备盘缠吧你得花时间吧)。

为了将消息从你的PC上传到服务器上,需要用到IP协议、ARP协议和OSPF协议。

我们都知道,你的PC和百度服务器之间一般会有许多路由器之类的东西,IP协议指定了出发地(你的PC)和目的地(服务器);你的数据会经过一个又一个路由器,OSPF决定了会经过那些路由器(用一种叫路由算法的玩意,找出最佳路径);从一个路由器怎么传给下一个路由器?这是ARP协议的JOB,
ARP负责求下一个节点的地址(我们不止是要目的地,还要中间节点的地址)。IP协议使用的是IP地址,整个发送过程中只涉及出发地和目的地2个IP地址,
而ARP协议使用的是MAC地址,整个发送过程中涉及到每一个节点的MAP地址

现在,我们能和服务器通信,还建立了TCP连接,下一步干嘛,当然是用HTTP协议请求网页内容咯。

你发个HTTP请求报文给服务器,如果服务器禁止你访问它就给你回个”Forbidden”,如果它暂时挂掉了就给你回个“内部服务错误”,如果它正常才给你回个“OK“并将你要的数据传给你;如果你还需要其它的东西再去跟它要(它一般还会给你的-_-)。

你收到了服务器的回复,是一坨HTML形式的文本。浏览器必须要能够理解文本的内容,并快速地渲染到屏幕上(浏览器一般用有限自动机来理解文本内容,渲染的话就各看本事了,之所以微软IE卡成狗而谷歌浏览器很6,就是它们的渲染速度不同…)

渲染出来后,你就看到百度的首页了

邱永臣与世界(S)

1.陈达有时候不免得也会觉得很孤单,一方面,身边的女朋友时不时会表现得非常冷漠,不接受陈达的谈判意愿;另一方面,独在异乡为异客,想家的时候,举目四望,家又在何方?
陈达6岁失去了父母,依旧被大葱划为了幸福家庭出身的孩子,说:“幸福家庭出生的孩子,对爱情的憧憬,那是饱暖思淫欲,没事吃饱了撑。

2.在这个陌生的世界里,陈达有种投胎转世的错觉,想起大师说过大海把沙漠染蓝是一种趋势,他心想:“大师那司马老贼,还想用落后腐朽封建迷信的西方思想来毒害我这德育智体美的优秀青少年。”

3.环顾四周,全都是白领阶层,身上都有100150万的贷款,加上利息,那就是170250万了。

4.楼市就像股市,要把手中的房子卖出去,必须有人接盘,如果没新的接盘侠涌进来,手里的房子会变成实打实的贷款,某种程度上,楼市是一个庞氏骗局,现在可以思考一下为什么政府鼓励二胎了。

5.送走了移民监里的另一个囚徒,陈达开始盘算自己的脱困大逃亡计划。有囚徒说:“1096号牢房在歌唱,我的一生,都在歌唱”,《1942》里头,老东家说:“我知道怎么当东家”,路就在那儿,逃亡计划,陈达心里慢慢地有了数。
自打自己落入新贫困阶层后,总感觉有股力量暗中捣乱。如果再进不了美国,家里很快就揭不开锅了,不过既然自己知道怎样才能当上东家,大逃亡也不是不可能。

6.那牛蛙修炼路径,造价越来越高,屌丝底层觉得再努力奋斗可能也没用,区别也就是工地过劳死还是电脑前过劳死,人是要活下去,生存下去,但总有些屌丝爱思考人为何要活下去。
这种中产里的叛逆和底层屌丝里的觉醒者将来如果在一起,就会变得可怕,所以王者农药啊,网红奶茶之类耗费人时间,精力,金钱的产品不能停。
逼婚,催婚,孩子,二胎等宣扬家和万事兴束缚人的意识形态更不能停。
同时陌陌之类的软件也是需要的,发泄掉一点过多激情。
这样,一生又那么愉快的过去了。

7.陈达有时候会感到疑惑:和亲人或是感情非常好的朋友相处,应该抱着为对方好的心态,指出对方做得不够好,还是以事不关己高高挂起的态度,睁一只眼闭一只眼呢?前者,纠错多了难免有冲突矛盾,后者,叫旁人听着了恐怕落得不孝子、轻浮男等高雅的称号。

8.自从陈达染上了失眠的毛病,有时躺在床上迷迷糊糊,时而听见大师兄呼唤自己,时而有二师弟叫自己去救师父,梦中的美景,美不胜收,可惜啊,不能搬到现实中来。
为了山间清流的小溪,为了宽阔的草原,流浪远方流浪,还有还有,为了梦中的橄榄树。咦,为什么会为了梦中的橄榄树去流浪呢?

邱永臣与世界(R)

1.这些道家说的道,佛学家说的佛,神学家说的神,儒家说的礼,哲学家说的智慧,光学家说的光,电学家说的电,告诉我们的是:“一开始悟空一个跟斗十万八千里,也逃不出佛的手掌,而最后悟空,也成了佛。”

2.我不下地狱谁下地狱,悟空,等你明白了这句话,自然会回来和我说这句话的,哦弥陀佛。

3.世人皆说大师好,大师的学生出名了,大师的老师他在哪儿,环顾四周明白了。

4.大师说:“成熟的人有个特点,能收住张口而出的话,能说出自己起鸡皮疙瘩但能安慰人的话。还有一个特点,把精力花在有用的地方,不做无用功”,陈达觉得很有道理。

5.陈达说不好普通话,在一些场合往往刚开口说两句,就被人说是:“人品差、素质低、没文化,我们好好的北京人都被你玷污了”。

这时陈达只好赔笑脸:“哎呀,咱这不从落后偏僻小山区来大城市混口饭吃嘛?以后一定会虚心学习,不拖后腿,希望您多多担待多多指教”

6.从梦中醒来,陈达惊出一身冷汗,幸好自己身处男性多阳气足的地方,否则梦里的五大鬼将、十万冤魂和百万粽子,将撕裂时空,追到这里。

7.从来就不相信什么神仙皇帝,也不相信牛鬼蛇神,可是别人坚持指出你是魔鬼是迷信,你也不能不理会。

弹性的定义

可用性定义

可用性 = MTTF / ( MTTF + MTTR )
MTTF:Mean Time To Failure,平均失效时间,指的是系统的正常运转时间
MTTR:Mean Time To Recovery,平均修复时间,指的是系统从出现故障到恢复的时长

Read More

邱永臣与世界(Q)

1.杨振宁李政道证明弱相互作用力之间的宇称不守恒,可惜一个比另一个大6、7岁,老了之后不说话,把弱相互作用力变成强作用力,彼此以毒攻毒,以牙还牙,以眼还眼。

2.如大葱一类学习的主观能动性比较强、超前选课的孩子,恋爱这门大学的必修课程,也不知道他是从高中还是一进大学就选上的。

3.你看我们班上某些同学,谈了吹,吹了谈,感情真那么好,真爱得那么深?不见得,那都是场面上的问题。

4.陈达质疑道:“为什么我们要君君臣臣父父子子,为什么做人要仁义礼智信,为什么人要孝顺,父母在不远游游必有方,爸妈想念了,就得过年回家看爸妈,如果自己不想念单单是爸妈想念,还有必要回家吗?”大师说:“瞧你又被西方极右的保守落后思想腐蚀了,又在那质疑儒家思想,质疑我们是否被洗了脑……”

5.“where are you now?you fade away, so lost”,想跟着唱几句,可若真唱了,恐怕能让世界充满爱,让大海把沙漠染蓝,让和平的福音传遍,让人类能在西伯利亚、北冰洋和加拿大的永冻土上居住,飞出太阳系进一步探索宇宙的奥妙,想到这,邱永臣就不唱了。

6.邱永臣说:“瞧你又引入西方极右的保守的价值观了,进化论在目观短浅视野狭窄的人眼中,是看着谁个大谁更强谁就能活下去,但是在群论里,人之所以厉害是因为人能群,不能群单打独斗是不可能胜利的。”

7.“轻轻地吻着你的脸,把你放在心上哥哥你放开我的手,弟弟我自己走”亲爱的听众朋友们,我们今晚的节目,到这里就结束了,如您喜欢,请明天继续收听我们的节目,祝您睡个好觉,做个好梦……

8.“想开点,看开点,看远点,有些人是不该爱的人,我看你,就是要爱上那不该爱的人”,可不管邱永臣怎么劝,大欧总表现犹犹豫豫,沉迷于科学研究工作,死活不肯出来感受爱的文化。

9.8个音符里前3个“哆 唻 咪”放在一起,叫大调,给人力量,使人欢快。前3个加上第4个“发”,组合起来叫小调,使人哀伤,令人幽怨,这是为什么?学过量子力学,尤其是有微积分理论知识的童鞋很容易能看出,前3个音符的频率,在直角坐标轴上是平滑的曲线,而第4个音符,却很坎坷,4个音符放在一块,平滑曲折,失意得意,上升下跌,快乐忧愁,就这么来了……

10.总结下来,乡村民谣无非是:“我的猫离开我了所以我很伤心,所以我要弹吉他”,摇滚流行无非是“我女朋友不爱我了所以我很伤心,所以我要在疯癫中放纵”,blue嘻哈无非是“我女朋友离开我了所以我要胡说八道”……这叫万曲归宗。

11.在中大,童鞋之间谁也不服谁,平时用动物表情包互相问候算是轻的,姓王的同学很容易被人叫做wangba,据大师散布的谣言,wangba在法语里边可以做last name。

12.陈达回想起,大学宿舍里一个爱发脾气的天才,发脾气时特早起床弹吉他,反反复复是嘟嘞咪发,既影响同学们早上睡眠质量,也暴露出其吉他技艺的低水准。

13.大师说,人家要装英文字母表里的第二个字母,你有什么方法,台湾人失恋后喜欢弹钢琴,你这位同学,我估摸着他已经计划好失恋后弹吉他。

14.虽然陈达不屑于中大,觉得里面都是骗吃骗喝的老混蛋,但是,如果没去中大的话,就遇不到大欧、陈奕迅、台湾男、小彭、羊男、拖鞋哥等等有意思的大佬。

15.何从那么客观,双眼失明后也陷入烦躁,每天感觉自己像个废人,没人理解,没人明白,这种感觉确实不好受。

16.人类之子,大聪,最后还是孤孤单单走向黑暗的舞台,台下观众不耐烦陆续散去,台上的大聪却越唱越尽兴。

log4j日志保存服务器

在之前的『从0到1理解Java Web』的『日志框架』部分,我们知道了如何让项目打印日志在控制台上,方便我们调试观察代码的运行,这篇文章主要是介绍如何把日志打印输出到服务器文件上保存起来,上线后借助日志文件找到Bug。

这里分3部分,一个是流的概念,一个是log4j配置,另一个是打印spring自身的日志。

在linux中有流的概念,从一个地方流入(比如键盘,比如扫描仪,比如文件),流出到另一个地方(比如控制台,比如文件,比如屏幕),上一次我们实现了『从日志系统流出到控制台』,这次实现『从日志系统流出到文件』即可。

把日志的去向从控制台改到文件,需要改动哪里?这牵扯到第二部分,也就是log4j的配置。

log4j配置

log4j有3个组件,loggers/appenders/layouts,它们一起协同工作,指定了日志内容的格式,根据日志的类型与级别,将日志输出到指定的位置。

loggers

指定日志输出的最低级别,把级别信息传给appenders。
日志级别由低到高分别是:Trace < Debug < Info < Warn < Error < Fatal,只记录大于等于当前级别的信息。

appenders

指定日志的输出方式与保存位置。
主要有以下几类appender:
1.ConsoleAppender :将日志输出至控制台
2.DailyRollingFileAppender :将日志输出至文件,日志文件每天切割
3.FileAppender :将日志输出至文件
4.RollingFileAppender :将日志输出至文件,日志文件按指定的大小进行切割
5.WriterAppender :将日志以信息流的格式发送到指定位置

layouts

指定日志内容的格式,比如输出为Html等。

这3个组件的具体配置都在log4j.xml中。把lo4j4.xml修改为以下的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?xml version="1.0" encoding="UTF-8"?>

<Configuration status="info" packages="com.dianping">
<Properties>
<!--日志输入路径-->
<Property name="log-path">/data/applogs/${sys:app.name}/logs</Property>
<!--日志输出到cat格式-->
<Property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [${sys:app.name} ${hostName}}] [%-5level] [%t] [%c] - %msg%xEx%n</Property>
<!--日志进入存储中心的格式-->
<Property name="dw-pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} ${hostName} ${sys:app.name} %p %t %c %msg%xEx%n</Property>
<Property name="scribeCategory">${sys:app.name}</Property> <!--日志需要和日志采集的一致-->
</Properties>

<Appenders>
<!-- 记录除用户行为日志外的所有信息 -->
<RollingFile name="appAppender" fileName="${log-path}/app.log" filePattern="${log-path}/app.log.%d{yyyy-MM-dd}">
<PatternLayout pattern="${pattern}"/>
<Policies>
<!-- 这里的interval由filePattern中的最小时间单位来决定,如果filePattern 中是天,这1就是1天-->
<TimeBasedTriggeringPolicy interval="1"/>
</Policies>
</RollingFile>
<!-- 独立的 error appender 便于排查问题 -->
<RollingFile name="errorAppender" fileName="${log-path}/error.log"
filePattern="${log-path}/error.log.%d{yyyy-MM-dd}">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
</Policies>
</RollingFile>
<!--打印日志到控制台,方便调试-->
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level [%c] - %msg%n"/>
</Console>
</Appenders>

<Loggers>
<Root level="INFO">
<AppenderRef ref="appAppender"/>
<AppenderRef ref="errorAppender"/>
<AppenderRef ref="Console"/>
</Root>
</Loggers>

</Configuration>

另外建立classpath:META-INF下建立文件app.properties(即mai/resources/METa-INF下),在里面指定项目的名称,内容如下:

1
app.name=my-project-name

随后启动项目,进入/data/applogs/my-project-name/logs目录,即可看到日志文件。

到这里,我们已经成功地将代码里的日志输出到文件里。每天保存,可是,如果你仔细点观察,会发现日志文件里并没有spring和其它第三方库的日志,这可是大问题,很多时候Bug是spring的bean注入失败或找不到对应的类引起的,如果没有spring的日志,我们很难追查到真正原因。

监听web运行中第三方库日志(如spring)

监听web运行时的日志,那么我们就能监听到所有日志,包括spring和其它技术栈的日志。

在web项目配置文件web.xml中加入对应的监听器,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<context-param>
<param-name>log4jContextName</param-name>
<param-value>poseidon-settlement-service</param-value>
</context-param>

<!--由Spring载入的Log4j配置文件位置 -->
<context-param>
<param-name>log4jConfiguration</param-name>
<param-value>classpath:log4j2.xml</param-value>
</context-param>

<listener>
<listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener>

<filter>
<filter-name>log4jServletFilter</filter-name>
<filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>log4jServletFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>

<!--Spring默认刷新Log4j配置文件的间隔,单位为毫秒 -->
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>60000</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

同时引入log4j-web包,启动项目,即可。

邱永臣与世界(P)

1.我不能忍受和她争吵分离后的寂寞,我不停地翻看各种书籍,沉迷在书的世界里,尽量让我这段时间里不闲着。我下定决心,再遇到她的时候,她将看到一个完全不同的我。

2.肖总啊肖总,我们怎么敢收你的钱呢?要不我们给你发一个碗,你帮我们去吆喝“有钱的捧个钱场,没钱的捧个人场”,收到的钱呢,你一半我们一半。

3.责任感还是蛮重要的,很多同龄人说:“我还不想保护自己关心的人,太难了,我不想一步登天”,邱永臣想:“很多人都是这样吧,不想长大,不想肩负责任”。

4.窗外的风景嗖嗖过,回过头看车里液晶屏粗糙的红字,邱永臣恍惚间厌倦所谓的科技,向往无尽的自然。

5.悲情所在的地方往往是那艺术和文学洋洋洒洒、血流如注、泪如泉涌之处,什么伤痕文学,上山下乡知青文学,都比不上囚徒文学宏伟壮观。

6.陈达问大师:“几点的飞机,时间到了没有?”
大师说:“早就到了,这可能是我们最后一次见面,所以多聊会儿。”

7.谈到这种时候,大师最喜欢引用的,是鲁迅先生写的《藤野先生》:“中国是弱国,所以中国人都是低能儿,分数在60分以上,便不是他们自己的努力了”

Quartz源码分析

零、简要

按照上一篇的介绍,Quartz是个作业调度系统,核心组件有Job/Trigger/Scheduler等,如何使用Quartz我们已经知晓,此次细心看看其内部的代码逻辑。

Read More

对Quartz的学习和研究

简要

Quartz是一个用java编写的job调度框架。
支持数据库,也就是说它可以连接数据库…
支持集群部署,您可以同时在多台机器上部署一个Quartz实例,job数量少时集群部署可以提高可用性…
支持cron表达式(此条是真的)…

尝试使用Quartz

程序员言道:”show me the code”,说得就是在学习任何工具框架之前,最好先跑一跑代码,对框架有第一印象之后再学习。Quartz是个job调度器,没有使用过它的童鞋一时半会儿无法理解调度器,因为job调度是个领域,对该领域没个了解是不行的。

简单地理解,Quartz运行的时候有3部分:Job、触发器和调度器。Job是我们自己写的逻辑代码,比如说发送一封秘密邮件。触发器,配置了Job什么时候执行。调度器,是调度框架的核心,没有它,Job和触发器没有意义。总而言之,言而总之,调度器根据触发器的配置,在特定的条件下『触发』特定的动作,比如我们设定触发器在每天凌晨1点触发我们的发邮件Job,调度器会在每天1点定时启动Job。

Read More