Becomin' Charles

算法 | LNMP | Flutter | Mac

Becomin' Charles

OAuth-cartoon

最早的OAuth诞生于2006年11月,当时,程序猿布莱恩·库克(Blaine Cook)正在实现Twitter的OpenID。与此同时,Ma.gnolia(一个社会化书签服务2005.12.25~2009.1.30)需要一 个解决方案,允许使用OpenID的成员,授权Dashboard Widgets(Mac系统的桌面小挂件)访问它的服务。这样库克、克里斯·梅西纳(Chris Messina)和来自Ma.gnolia的拉里·哈尔夫(Larry Halff)与戴维·雷科尔顿(David Recordon)会面,讨论在Twitter和Ma.gnolia API上使用OpenID进行委托授权。他们的讨论,得出一个结论,没有开放标准完成API访问的委托。

阅读全文 »

好吧,我必须要承认,我是一个标题党来的。本文英文名称意思比较准确。什么?你没看到英文名称在哪?不是写给你看的,你当然看不到。

在Web开发过程中,你总是因为各种理由,需要跟服务器打交道,因为各种理由需要承担一点点运维工作,哪怕你需要运维自己的blog,比如用Linode这种东西。那么服务器运行,就少不了log,log不少,就不得不翻滚,就是rotate,不知道中文是啥……

阅读全文 »

我所在的团队负责研发一款企业应用,在其管理后台,需要用到日期选择器,因为是这种企业软件,所以很多场景需要用到报表,报表按照月查看,按照年查看的很多,所以在使用日期选择器的时候,就需要按月选择和按年选择的场景。

但是 jQueryUI 只提供了标准的 DatePicker 进行日期选择,却没有提供专门选择月和年的选择器。所以,这时候各种交互设计和前端设计师开始各县神通了,各种自己发明的交互方式。

https://github.com/eternicode/bootstrap-datepicker

这个项目是我通过 Google 搜索的一个老外发明的,深得我心,感觉保持交互的一致性和美观性。推荐给诸君。

很多年了,谈这个问题的人太多了。不过我觉得,恐怕方法科学,结论也科学的不多。

先来说几个方向,从网站优化的一般处着手。博客也就是个内容站。关于内容站,我们可以做点什么呢?

Web 服务器,选什么?我推荐还是 Apache,目前公认最稳定的服务器,没有之一。这是题外话。那么 Web 服务器的配置,正确么?注意我没问是不是最优,就先问正确不?MPM 至少有三种模式,你用哪种?为什么?这种模式的参数配的多少?是推荐值么?最佳要自己测,但推荐数值还是有的。有人说应该把 AllowOverride 关掉,你关了没?为啥关,为啥没关?

伺服静态文件的能力不行,是否考虑前面套一层 Nginx?

接着是 php,apc 装了没?

然后,该整数据库了,那么,MySQL 是否配置正确了?查询缓存配置了没有?配了多大?索引缓存配了没有?配了多大?不是越大越好噢…

到这里,差不多,都正确了,我们再来看,是否优化了。说到这里,就不得不谈指标,抛开指标谈优化,就是耍流氓。很多优化文章你可以看看,有没提这个。比如优化目标是什么?降低负载,不降,虚拟主机就禁止我用;提高首页访问速度,用户至上;

在这个目标基础上,指标是什么?CPU 占用降低一半?首页呈现短于 1 秒?

这时候,需要闭环反馈了,我调了个什么,产生什么结果?你能立刻知道么?通过什么知道?别说是目测,那不准。

为什么谈了半天,没说 WordPress?因为你要西瓜,不要芝麻。有些小事,效果很好;有些费劲,效果很差。说到 WordPress 就是后者。你要相信,WordPress 再怎么差劲,全球几百万人用着,不会想不起来优化,所以里面不敢说最优,绝对跟慢,差劲,这几个字眼挂不上钩。有人说,太重,说得是功能,你要简单,搞静态页啊,那个肯定快。

怎么搞 WordPress?首先能有办法纯静态么?有个 cos-html 的插件,全站静态化,那速度,没得说。

不行?那缓存能搞么?super cache 这种插件就好一点了。

还不行?最麻烦,效果最小的东西来了,上 xhprof,做分析,有些,能看出来,有些看不出来,看不出来的情况居多

& 这个符号在C语言和PHP里都是取地址的意思,我们通常怎么念这个东西?“and符”,估计很多人跟我一样念吧,因为在英文里,这个符号表示“and”这个含义。

* 这个符号,在C语言里表示指针,怎么念?“星号”,大概这么着吧,哈哈

# 这个符号,在C语言里,表示预编译指令的前导符,也是Linux环境的注释,怎么念?“井号”,有了C#,念C Sharp,但是没人管#念Sharp,哈哈

如果像这样去念三个符号,你在中国会生存得很好的,没啥大问题。但是我在听国外的公开课,彻底傻逼了。

& 这个符号的名字是 ampersand,含义就是“and”。听到这个词,要意识到老师在说啥。

* 这个符号的鸟语名是 asterisk,一种符号,在文章中一般表示,底下有脚注。

# 这个符号的名字是 hash,是不是很难受的感觉,在英文里的意思是表示数字,比如我家住18号401,写地址可以写成 #18, 401,另外在美国还用于表示磅这个重量单位,比如 2# of sugar,大概两斤糖。

一眨眼,使用Yii框架已经有两年的历史了。今天,改代码改得郁闷,我来吐吐槽。

Yii框架的官方文档,其实介绍了关于最佳实践的问题。就是Controller里该写些什么,Model里该写些什么,View里该写些什么。但是实际情况到底是怎么一回事呢?

Model,这里应该写什么,按照原有的最佳实践,这里应该实现所有的业务逻辑的。这个毋庸置疑。但是,Yii框架干了很浑的一个事情,就是做了一个ActiveRecord的东西,然后,各种案例教学,一搞Model这个问题的时候,好像就在讲这个AR怎么个好法。然后Model莫名其妙就跟DB搞一起了。然后大家就习惯性的提到Model总想到DB,再然后,Model就成了一个DB接口一样的东西。注意到这里的心态转变没有,Model跟业务逻辑的关系被淡化了。事实上,像我这样的公司,都不允许在Web服务器上连接DB,必须透过中间件,结果Model就惨了,彻底沦为了访问中间件的接口封装层。然后到底该如何实现业务逻辑呢?实现到什么粒度算是实现了业务逻辑呢?这个根本没有给出一个指导。比如,创建用户这个业务。你可以在Model里实现一个addUser的方法,把所有事情都做了。你也可以实现一个addUser,checkExist,sendEmail,然后在Controller里 if ($m->checkExist() && $m->addUser()) { $m->sendEmail() },你看,这到底算不算把业务逻辑写在了Model里呢?前一种,addUser在内部做完所有的事情,后一种,实现了三个子操作,在Controller里组装。前一种,Controller里干净了,就一行代码,但是复用性极差,因为别的场景,比如从文件向空DB导入用户的时候,就没必要sendEmail和checkExist,就无法复用第一种的代码,第二种的相对细粒度的,就容易复用。不是都说代码复用么,blahblah……结果人们很有很强的动力用第二种。但是,检查存在性,然后写入存储,最后发邮件,这个事情到底是不是业务呢?所以,Model里实现粒度的指导,至关重要。结果根本没有任何指导。最后,Model的实现,被彻底原子化了,而且粒度切分,按照个人的习惯而定,有的粗,有的细,最后,Controller就很恐怖地容纳了巨量的业务逻辑。

Controller,这里该写什么,其实是最模糊的一个地方了,其实正确的用法,我一直这么理解的,就是应该用Model实现一切业务逻辑,Controller里,就应该选择合适的Model,执行业务逻辑,然后将结果传递给用render渲染出来的View。在实际使用中是什么样子呢?比如有一个公用的预判条件,本来这种应该写在Model里的,但是很多Action需要这个预判,但是又不一定需要那个Model,结果这个预判被写在了Controller里面。甚至更广泛的一些判断条件,被写在了所有Controller的基类里。再比如,用户身份这个问题,应该封装在User组件里的,但是实际上,那样做理解起来太困难,很多人都搞不懂这个组件结构是怎么回事,然后为了方便,干脆把身份写在了所有Controller的基类里面,然后把身份id赋值给了Controller的公共变量。这简直就是灾难。

再说说这个View,这个本来是最简单的部分了。结果呢?按照条件展示页面的某个部分,总要判断某个条件吧,这个条件怎么来?应该在Controller里,由Model来计算。但是如果这个条件很通用呢?结果这个就被放到了Controller的基类里面。然后在View里直接调用Controller的函数,这个就是大错特错的一个事情。等于View知道了Controller的结构。最关键是,这个判断条件,根本就是业务逻辑的一部分。最后一团糟的就是连View里也间接透过Controller融入了业务逻辑。

以上我说的每种错误,都有看似简单易行的正确做法,但是为什么大家都没有去遵守呢?当所有人都犯错的时候,是不是该考虑一下,到底什么地方有问题呢?

有些很基础的东西,一直以来也就没有搞懂,其实,究其原因,还是不求甚解。关于Bash的种种,便是如是。接下来,我来过一点man里面有的东西,经常看man的人,就请自动飘过吧。

Bash是shell的一种,运行中的Bash有两种属性(状态/模式),一种,是否interactive shell(交互式Shell),另一种,是否login shell(登录Shell),然后,运行中的Shell排列组合有这么几种:

  1. 登录交互式Shell
  2. 非登录交互式Shell
  3. 登录非交互式Shell
  4. 非登录非交互式Shell

关于这两种东西的定义也是非常简单明了,但是非常不容易记忆:

交互式Shell:没有非选项参数,没有-c,标准输入和标准输出与终端相连的,或者用-i参数启动的Bash实例。可以通过探测PS1变量是否设置或者$-返回值中是否包含字幕i来判定。

什么是没有非选项参数?比如bash ~/myscript/clear_temp_files.sh这样执行的Shell脚本的Bash实例,就不是交互式Shell,因为脚本的路径,就是非选项参数。

-c又是干什么的?就是使用一个字符串作为Bash的传入参数,比如bash -c ‘ls -ahl’,这种Shell进程也不算是交互式Shell。

登录Shell:第0个参数以-号开头的Bash实例,或者用–login参数启动的Bash Shell。

更加诡异了,什么叫第0个参数以-号开头?你只要随便登录一个*nix系统,Mac也行,Linux也行,然后echo $0,你就明白了,惊讶吧,出来的值竟然是-bash。真的是以-号开头的!!

搞不清楚这两个东西,到底有没有什么决定性的关系呢?事实上是没有太大关系的,又一个事实是我工作四年了,还没搞清楚这点东西。I survived. No big deal. 什么时候出问题了呢?比如当你配置了一个crontab,然后你发现,我擦,为毛总是不执行呢?又然后,为啥环境变量没有呢?一般,crontab里的东西都属于运维脚本,用不着一个小开发去写,所以,你survive的机会师很大的。

好吧,我漏了很重要的一块内容没说。

就是Bash启动的时候,要加载哪些配置文件的问题。搞清楚上面两点,就可以搞清楚Bash的配置文件到底是怎么加载的。对于一个登录Shell(不管是不是交互式的)来说,一般会按照顺序加载如下四个配置文件,如果存在的话。

  1. /etc/profile
  2. ~/.bash_profile
  3. ~/.bash_login
  4. ~/.profile

对于一个交互式非登录Shell来说呢?加载的文件又不一样了:

  1. /etc/bash.bashrc
  2. ~/.bashrc

所以,我们就会搞清楚一些事情的原因。比如一个crontab的bash脚本,到底会不会执行如上的配置文件,答案是否定的。一个crontab脚本,没经过处理的话,既不是交互式Shell,也不是登录Shell,所以上面的都不会执行。

怎么处理?比如可以把shabang改一下#!/bin/bash -l让脚本用登录Shell来解释执行,就可以加载/etc/profile或者,调用Bash解释器,加-l参数也可以。看似很简单对吧。

另一个遇到的问题,为什么在Linux,我们总是配置/.bashrc但是在Mac下,我们配置就没有用呢,要去配置/.bash_profile才行?哈!什么情况加载/.bashrc,上面说得很清楚了,交互式非登录Shell,那在Mac下,你打开Term,echo一下$0,看看,前面是不是有个-号?说明这是交互式的登录Shell,当然不会加载/.bashrc了。实属正常。你肯定要问了,为啥Linux下没问题呢?你打开/.profile看看就知道了,这货竟然在/.profile文件里面source了~/.bashrc!啊!谜题都解开了~

一般在开发大型系统的时候,都免不了要分库分表,一种常见的分表方案,就是按照用户的id来进行分库分表。

我们的产品id,是数字,因为传统和一些习俗原因,很多数字对中国人有着特殊含义。比如大家不喜欢4和喜欢8,当然只是个例子。然后我们项目开发就遇到了一些麻烦,就4和8这个例子来说,就会产生这么一个麻烦。如果按照模100分表,那么4号表里是空的,8号表里压力很大。然后,就有了各种办法,比如模256。再比如,md5以后,取后两位。这两种都是分了256个表了。

结果有一天,我看到一个系统,分表方案是模97。我就觉得这个数字很蹊跷,问了下开发。这个97很完美地解决了4和8那个案例。原来,这个97是个素数。我有一种当头一棒的感觉,原来如此啊……

因为放在VPS上的博客一直Nginx 502和500,我去看了一下access.log,不看不要紧,一看下一跳。我的博客是个没多少访问量的博客,竟然每秒也能产生数十条的log,而最糟糕的是,这些log,都指向了同一个文件,xmlrpc.php。

这个xmlrpc.php,其实是WordPress博客提供的一种API接口,如果你使用Live Writer或者MarsEdit这类软件,这个xmlrpc.php就是必不可少的一个东西了。其实就是使用xml文件描述的,远程方法调用。频繁地访问这个API,非奸即盗啊!试密码,或者发垃圾评论,或者发垃圾文章,太糟糕了。虽然这么久了,没有被攻破,但是看着总归不爽。

一般方法是将访问的IP都找出来,然后全部iptables禁用掉。如果你不用客户端,直接把xmlrpc禁用掉好了,省得让贼惦记着。

1
2
3

grep "POST /xmlrpc.php" access.log* awk '{print $1}' sort uniq -c sort -nr

上述命令,用倒序列出所有攻击得IP和攻击次数,对于攻击最多的,直接iptables就好。

然后,以前ishow也谈过的,ssh试密码的问题,可以对auth.log搜索一下“Failed password”这个关键词。我看了,我自己的,是没有的。又看了管理的两台朋友的服务器,都有10万这个量级的攻击次数。我大体想了想,可能因为我一开始习惯性更换了sshd的端口,导致攻击者找不到目标了的关系。所以这个问题,我建议直接更换sshd的端口,很方便。