分类目录归档:学习

尝试LeetCode

起因

OJ在学生时代应该都有所接触,作为程序设计与算法课程的实践内容也在一些OJ上做过少数的一些题目。不得不说,多年的习惯让在OJ上解题成为了一件很愉悦的事情。

工作后,原本薄弱的算法知识感觉消失殆尽,尽管在每天的工作中,组装、修改成为了工作的主题,可是总觉得自己不应如此,希望自己能保持毕业前那样积极的学习态度,希望自己能把之前的自主学习和思考的习惯保持下来。然而自己在每天的工作之后,惰性还是占了上风,阅读自然不少,可是这类基础的训练却扔下了。

本科期间由于学校身边的环境的缘故,自学了Java的基础编程。这半年对Android开发很感兴趣,再次接触Java,自己实现的过程中,感觉自己再次的丢掉了很多东西。

工作两年,经历了最开始的模仿、学习阶段之后,也尝试了各个方向,单独承担系统的开发维护工作中,更是觉得基础的知识,诸如网络OS等基础知识在解决问题上能对思路起到打磨的作用,避免自己掉进 case by case 的坑里。积累经验当然重要,但是个人觉得更难得的是学会如何找到解决问题的方式,面向StackOverflow编程并不是一个好的选择。

近期看到 云风 大牛的关于反转单向链表微博,自己下班尝试编写了一下,也是花了一会儿时间才能顺畅的写完。这两天也是看到liaohuqiu 大牛发起的 LeetCode攻克计划,觉得是时候重新开始修行了。

目的

LeetCode 的目的主要有两个:

  • 从基础开始,重新学习Java编程
  • 重新学习算法知识

第一个理由可能引人发笑,然而这确实是一个手段。自己在学习编写Java程序的过程中曾经过分的贪图速度,跳过了很多自认为基础的语言上的内容,在比较自己编写的代码与熟练的同事的代码中,更能有所体会。

计划

基于第一个原因,所有的LeetCode解题都会使用Java完成。

目前来看,一共有83道 Easy 题目,167道 Medium 题目,以及74道 Hard 题目。

不求过分贪心,希望半年内,我能把所有的 Easy 完成。

对于解决的题目,将会在blog里贴出自己的解题方案以及简要的解题思路,同时在解题过程中,尽量通过完备自己的思路和case解决问题,而不是通过尝试AC来解决问题。

已解决问题 [2]

two-sum Easy

add-two-numbers Medium

使用Nagios监控Redis-按内存使用率监控

概述

本文是 使用Nagios监控Redis 的补充记录。

根据前期选用的插件,通过直接针对 used_memory_rss 设定监控阈值完成监控,而这一阈值的问题在于是使用字节数的表示的,如果要按照36GB70%设定阈值监控,就需要将监控的值设定为(结果已四舍五入):

这一数字对于config文件来说,以及监控用户来说并不友好。

解决

插件本身也提供了直接通过使用率进行监控的使用方式,我们所需要做的就是告知插件对应实例的最大内存容量,即:

这一参数可以使用人类友好的单位表示方式表示数值。

同时设定阈值需要使用 -m 参数,即:

即通过逗号分隔 warncritical 两个级别的报警阈值。如同手册所说的,必须与 -M 同时使用。

我们所需要做的就是在 /nip/etc/objects/commands.cfgnipnagios安装目录的缩写,根据实际情况决定)中新增或者修改一个命令:

同时在 /nip/etc/conf/services.cfg 中使用这一命令:

当然,也可以修改插件完成。

以上。

git根据仓库url修改用户信息

起因

日常Coding使用git的一个问题是,公司工作和个人项目有时候会使用不同的用户信息,例如公司项目要求个人信息必须为your_name@your_company.com的形式,而你自己在使用Gmail,这里自然有些冲突,如果忘记在clone的项目中配置一下,极有可能会把自己的日常使用邮箱提交到公司的repo中,反之亦然。

虽然git本身可以通过--global进行配置,日常使用上使用都用自己的常用个人信息,但是公司项目每次都要单独配置也是做了太多无用功,那么如果能让这个任务更加自动化想必是可以提高工作效率的。

方案

解决的思路决定采用githooks进行处理,在每一次的commit操作前触发,判断当前项目的远端仓库url是否为公司url,若为公司url则修改当前项目目录下的git用户信息,即:

具体匹配操作运用了shellAWK的结合,个人感觉AWK在匹配以及字符串处理上更胜一筹,主要逻辑利用AWK完成。

主要逻辑如下:

其中通过awk的exit值向shell传递信息,通知当前状态,若修改完成,提示用户重新进行commit操作。

使用

GitHub上获取代码后,根据实际情况配置好匹配规则以及用户信息,将hook文件置入git安装目录下的/share/git-core/templates/hooks/之下,并chmod +x赋予执行权限,如在mac上通过homebrew安装的git,则会在类似:

目录下。

最后还需要指定项目的默认init模板目录,例如:

后续clone的项目都能起到效果了。

参考文档

参考了 @liaohuqiu 大大的博客文章git: 提交前强制检查各个项目用户名邮箱设置,同时修改了相关项目的代码,感谢!

TODO

在脚本中尝试帮助用户完成提交操作。

使用Nagios监控Redis

近期新上项目之后出现了后台服务的一些诡异的问题,追查之后发现居然有个Redis的实例把分配的几十G内存给用满了……

终于意识到之前“土法炼钢”的不科学的地方,惭愧之余迅速的想要给Redis加上基本的监控。

最初的想法是直接自己写脚本轮询各个实例的info信息,然后自行parse,当前运行Redis的实例不多,感觉工作量并不大,然而这时候想起组内之前的监控是在用Nagios,觉得为什么不让更专业的软件来完成这项工作呢?于是决定通过Nagios来完成监控。

以下会使用/nip指代Nagios的安装路径,以实际安装路径为准。

Nagios配置

Nagios分为Server和Client,通过各个插件完成对Client的监控,并且在Server中收集展现。

既然运用了Nagios,自然就要按照它的设计思路来进行使用,其实也就是使用合适的插件,同时也不想再造轮子,Google之后确定使用这一项目中的check_redis.pl插件(然而这一文件自2013年7月之后没有过更新了……),这一插件从功能上基本上满足了我对使用内存连接数key个数特定队列长度的监控需求。

这一插件基本上是帮助完成了从redis-cli -h host -p port infoNagios的收集展现过程,所以本身只要在Server上安装即可。

安装插件

安装插件本身并不复杂,只需要download & copy即可,即copy到/nip/libexec目录,并chmod +x赋予可执行权限即可。

然而,真正头疼的是这个插件的依赖安装,由于在服务器上初始化cpan的工作始终无法完成,无奈之下只好通过手工安装依赖。

这一插件的依赖分别是:

  • ExtUtils-MakeMaker
  • IO-Socket-Timeout
  • Try-Tiny
  • Redis

可以在cpan的网站上搜索下载tar.gz文件,解压后基本都通过:

这一过程完成依赖的安装过程。

配置Nagios

想要让监控正常的run起来,配置也是很关键的一个因素,个人认为,配置主要针对监控对象以及监控动作。

监控对象

对于监控对象来说,其实就是标明哪台Server上有着对应的服务,同时还可以对他们进行分组。

监控对象的声明,可以在/nip/etc/conf/hosts.cfg中的对应Server配置中增加一个别名,如:

声明的别名会在报警邮件中得以展现。

同时,需要在/nip/etc/conf/hostgroups.cfg中,为这一批机器分组,以便对一组实例完成监控。

监控动作

对Redis监控,首先要保证Redis实例可访问,不过这一点不用特别配置Nagios,我们需要做的只是针对我们关心数值,进行声明以及配置报警阈值即可。

首先需要在/nip/objects/commands.cfg中配置一个检查指令:

以上参数的含义可以通过/nip/libexec/check_redis.pl --help查看详情:

上述command的含义为针对主机$HOSTADDRESS$的指定端口$ARG1$,检查参数为$ARG2$(可以对照redis-cli info),在$ARG3$设定WARNING级别告警的数值,在$ARG4$设定CRITICAL级别告警的数值,同时生成数据(-f)。

在配置完监控指令之后,还需要针对之前的已经声明的主机组配置使用监控指令进行监控,在/nip/etc/conf/services.cfg增加一项配置:

此处根据个人的实际业务情况,当使用的内存超过28G(30064771072 = 40 * 0.7 * 1024 * 1024 * 1024,以下类比)或者key个数超过30w个时会发出WARNING信息,而在当使用36G内存或者key个数超过40w个时,发出CRITICAL警报。

Nagioscheck_command在参数前使用!,之后的数值针对每一个监控属性,~表示不关注,而对应位置的数值则标称各自的报警阈值。

最后

修改了配置之后,Nagios需要重启才能开始执行监控,那么为了防止因为修改配置而出错,需要通过Nagios先行检测配置文件的正确性:

Nagios的报错信息非常详细,基本可以直接定位到出错的行数。

检查正确之后自然就是重启,等待数据的到来。

又写了一个Hello world

又写了一个Hello world

近期有两天没有需求的日子,下周leader说让我去和前端学习一下,不过要先写个通关作业简单了解一下js。于是花两天时间又写了个Hello world。

简单记录一下,代码包含大量的调试语句,暂时不贴代码,后期还得试着填坑,写出一个完善的hello world。

要求

这个通关作业要求主要有下面一些东西:

  • 用Node.js自己实现一个简单的Http服务,实现BigPipe输出页面
  • 通过$Import加载js依赖模块
  • 通过register方式注册js模块
  • 实现自定义事件的支持,以及广播与事件代理

时间所限,自己只在chrome上完成了测试。

实现

整体设计

虽然是个Hello world,但是还是简单的思考了一下结构,大致的流程如下图:

流程图

Http服务

Node.js的Http模块的使用例子几乎是学习Node.js各类教程的标配了(比如七天学会Node.js……),实现的过程中基本上也是沿用了基本的写法。

其实感觉直接使用Express完成。

加载依赖模块

js代码如果能够把每一个部分代码拆分出来单独开发,只加载所需模块,那么对于开发维护,以及网络开销以及用户的体验上个人觉得都是有很大的帮助。自己理解是这一方式可以在浏览器端完成(比如requirejs最近同学推荐的seajs),也可以在服务器端通过主动的合并成单一文件返回给用户。

作业里面的方式是通过在服务器端合并的方式进行的。

由于对Node.js的异步编程思想并没有完全掌握,原先希望的通过异步的加载依赖文件的方式实现了一个下午也没有实现,眼看deadline就要到了,只能换成递归的方式进行处理,依赖文件首先读取并输出。

中间使用了UglifyJS2先对代码进行压缩操作,减小返回数据的大小,顺路去掉注释,简化匹配$Import语句使用的正则表达式。

在所有依赖完成读取之后,添加业务逻辑代码。

BigPipe

BigPipe工作中经常接触,这里的实现并没有特别之处,仍然是首先输出骨架,之后输出各个Pagelet。

具体来说这里使用了Node.js提供的信号功能,骨架输出完成之后会发出骨架已输出(设为skeleton_ready),同时计数器设定为Pagelet的数目。之后监听这一信号的各个Pagelet开始执行计算,完成之后直接输出用于渲染的<script>标签。骨架部分同时会监听Pagelet输出完成信号(设为pl_ready),之后计数器-1,当计数器为0时输出封闭标签</body></html>

Node.js通过repsonse对象的write方法返回值就能确定缓冲区是否已经刷新(参见文档),类似的,通过PHP实现的话还需要手动的进行ob_flush && flush。

从页面代码上看,大致是这样的一个效果:

代码效果

register

这里方法名任意,register的意义在于将当前的Pagelet(以下简称pl)的业务代码加入到当前运行环境中,register作为一个方法,第一参数为模块名称,也就是代码的路径,第二参数即为对应的回调方法。

register方法根据参数1,将回调方法绑定到指定的节点上,例如当前js对象的名称为Xe,pl的名称为pl.index.top,回调方法为func1(){...},那么在register操作完成之后就可以通过Xe.pl.index.top()调用func1(){...}

所有的依赖模块都通过这一方式进行组织。

自定义事件

对于自定义事件,目前了解到的应用场景,主要是单个pl中的模块之间的通信,实现上简单的通过保存自定义事件以及对应的回调方法的对应关系,通过对象的call方法调用自定义事件对应的回调方法。

为了能让回调能够异步的执行,还需要使用setTimeout方法。

广播

广播用于pl之间的通信,实现方式与自定义事件类似,但是不同点在于,广播中是通过频道对象调用回调方法,在每个频道中维护广播事件与回调之间的关系。

同理,也需要结合使用setTimeout方法。

使用上,每个模块都需要import这一个频道,同时向这个频道订阅指定的事件,绑定对应的回调方法。

事件代理

目前事件代理做法是将事件绑定到pl的顶部节点中,同时阻止事件进一步冒泡,由pl的顶级节点处理。

每个事件代理上都有一个对象维护回调方法与节点的对应关系。自己的实现中所有的节点绑定方法都会绑定一个共有的事件处理方法,在这一个方法中获取节点类型以及事件信息,之后调用具体的事件处理回调方法。

Todo

  • js依赖文件的异步加载

其他

有关静态服务器的实现,读了@朴灵大神文章《Node.js静态文件服务器实战》感觉有些启发。