Python使用logging为Flask增加logid

我们为了问题定位,常见做法是在日志中加入 logid,用于关联一个请求的上下文。这就涉及两个问题:1. logid 这个“全局”变量如何保存传递。2. 如何让打印日志的时候自动带上 logid(毕竟不能每个打日志的地方都手动传入)

logid保存与传递

传统做法就是讲 logid 保存在 threading.local 里面,一个线程里都是一样的值。在 before_app_request 就生成好,logid并放进去。

因为需要一个数字的 logid 所以简单使用 uuid.uuid1().time 一般并发完全够了,不会重复且趋势递增(看logid就能知道请求的早晚)。

打印日志自动带上logid

这个就是 Python 日志库自带的功能了,可以使用 Filter 来实现这个需求。

log_format 中我们用了很多系统自带的占位符,但 %(logid)s 默认没有的。每条日志打印输出前都会过 Filter,利用此特征我们就可以把 record.logid 赋值上,最终打印出来的时候就有 logid 了。

虽然最终实现了,但因为是通用化方案,所以有些复杂了。其实官方教程中介绍了一种更加简单的方式:injecting-request-information,看来没事还得多看看官方文档。

iTerm2进阶使用技巧

iTerm2 的优点这里不做赘述了,第一次使用的话可以先看看官网的介绍:featuresHighlights for New Users。本文主要是结合实际使用场景,介绍一些进阶使用技巧(基本的 Oh My Zsh、rzsz 等配置就不重复说明了)。

跳板机自动登录

现在很多公司登录服务器都需要先登录到一个跳板机然后再登录到目标机器,每次输入密码(一般还是动态的)很麻烦。一般的教程推荐使用 expext 解决这个问题,这里介绍一个更简单、直接的办法。

首先,要先解决登录到跳板机的连接复用问题,这个输入 ssh 本身的范畴,一般教程都是说在 ~/.ssh/config 增加下面的配置:

但这样有个问题,iTerm2 第一次登录的 tab 关闭后,就失效了,再登录就又要密码了。其实再增加一个配置即可。

之前的设置只是实现了连接复用,但 tab 关闭 ssh 进程结束后,连接也被销毁了,ControlPersist 项的意思是进程结束后连接还保持,再有相同的(ControlPath配置)连接,还能继续使用此连接。

再者,每次输入 ssh xxx 很麻烦(而且跳板机登录后还得输入 ssh xxx),当然你可以配置 alias+expext 但也不是太方便,特别是 Windows 转过来的。对此,iTerm2 本身也提供了很强大的 Profiles 功能,能一键登录目标机器(还可以设置快捷键)。

有些自己的常用机器,还可以复制一下这份基础的 relay 配置。

再加一行(Send text at start处)。

还可以把机器打个标签,然后页面上就能分组,方便选择。

还有一个,有时候会发现,有些机器一会儿没操作就会被断开 ssh,一方面可以设置 ServerAliveInterval,但作用不大,因为实际连接服务器的是 relay 跳板机。iTerm2 其实没有可以显式设置这个功能的地方,有些同学可能找到个这个配置: Continue Reading...

创建 redis systemd 服务

服务器操作系统一直使用的是 ubuntu server,因为安装软件很方便,直接apt-get install就行。但使用 apt 安装 redis 版本比较旧,也没有新的源,所有只能自己编译安装了。不过有个问题,自己编译安装的启动和重启比较麻烦(启动:/usr/bin/redis-server /etc/redis/redis.conf,停止:/usr/bin/redis-cli shutdown)。我在想能不能使用类似 ubuntu service xxx restart 的指令。

搜索了一下发现可以使用upstart来实现这个需求,但是这个在 ubuntu 15.04 已经废弃了,推荐使用更先进的systemd。在 /etc/systemd/system/ 下创建一个 redis.service:

其中主要是定义了启动用户,启动命令,停止命令。有个设置比较重要Type=forking,可以理解为 systemd 是一个类似 supervise 的守护进程,forking 表示服务管理器是系统 init 的子进程,用于管理需要后台运行的服务。同时还需要修改 redis 的配置:

然后就可以使用sudo systemctl start redis命令启动 redis 了。同时支持 stop、restart 等常用指令。启动成功后运行 sudo systemctl status redis查看运行状态:

可以看见 redis 已经正常运行了。可以尝试使用 kill -9 命令把 redis 杀死,你会发现 redis 马上又会被拉起,这样能保证服务能一直运行(当然若是服务有问题一直蹦,谁也救不了你)。若需要开机启动还可以运行sudo systemctl enable redis命令加入到开启启动项里面。

我们平常自己写的程序也可以依样画葫芦写个配置文件,使用 systemctl 来做服务管理,这种方式更加先进,还有一些其它实用的功能。

 

参考资料:

Ubuntu systemd service file for Redis, https://gist.github.com/geschke/ab6afa91b2d9dfcd5c25

systemd - ArchWiki, https://wiki.archlinux.org/title/Systemd

How To Install and Configure Redis on Ubuntu 16.04 | DigitalOcean, https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-redis-on-ubuntu-16-04

PHP单元测试-mock和数据库测试

在计算机编程中,单元测试(英语:Unit Testing)又称为模块测试, 是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。

本文主要是根据PHPUnit(The PHP Testing Framework)文档结合实例简单介绍一下 PHP 单元测试中 mock 和数据库测试。如果你是初次接触单测的话建议先看一下 PHPUnit 文档中的入门章节

通常来说是开发程序和单测是同步进行的,项目提测的时候核心模块都需要包括单测(报告),但这个要求在不同的公司、部门、项目组要求不一样。虽然单测会占用一定的开发时间但总的来说单测是利远大于弊,最大的好处是自己或者别人后续更新模块功能时不用担心对原有功能造成了影响而不知情。

下面是一个具体的例子,在 web 开发中这样一个场景可能很常见:PHP 提供一个帐号注册的接口供前端调用,接口先检验一下此用户名是否已经存在,不存在的话插入数据库,返回注册成功。接口代码是这样的:

主要调用了 Join 类的 signIn 方法。我们来看看 Join 类是啥样:

逻辑很简单,先调用 Db 类的 exists 方法判断用户名是否存在,不存在的话使用 insert 方法插入数据。Join 类是这次业务新加的,比较重要,需要单测来保障质量,但这里用到了个 Db 类,这个库是以前就有的(坑),可能会影响本模块单测的正确性,而且 Db 类需要连接数据库,比较麻烦,这种场景就需要 mock 了。本文说的 mock 是广义上的,包括 Stubs(桩件)和仿件对象(Mock Object)。

将对象替换为(可选地)返回配置好的返回值的测试替身的实践方法称为上桩(stubbing)。可以用桩件(stub)来“替换掉被测系统所依赖的实际组件,这样测试就有了对被测系统的间接输入的控制点。这使得测试能强制安排被测系统的执行路径,否则被测系统可能无法执行”。

将对象替换为能验证预期行为(例如断言某个方法必会被调用)的测试替身的实践方法称为模仿(mocking)

我们这里应用的是打桩的概念。signIn 方法有两个分支:用户名存在和不存在。所以我们需要让 Db 类的 exists 方法在输入某个(些)用户名的时候返回 true。主要使用 PHPUnit_Framework_TestCase 类提供的 getMockBuilder() 方法来建立一个桩件对象:

代码看上去很像是实例化了一个类,其实原理也和这个差不多,PHPUnit 通过反射机制获取到类及其方法的信息,然后使用内置模板生成一个新类。我们需要 mock 掉 insertexists 方法:

这里使用了桩件生成器的 setMethods() 方法来设置哪些方法被上桩,以下是生成器提供的方法列表:

  • setMethods(array $methods) 可以在仿件生成器对象上调用,来指定哪些方法将被替换为可配置的测试替身。其他方法的行为不会有所改变。如果调用 setMethods(null),那么没有方法会被替换。
  • setConstructorArgs(array $args) 可用于向原版类的构造函数(默认情况下不会被替换为伪实现)提供参数数组。
  • setMockClassName($name) 可用于指定生成的测试替身类的类名。
  • disableOriginalConstructor() 参数可用于禁用对原版类的构造方法的调用。
  • disableOriginalClone() 可用于禁用对原版类的克隆方法的调用。
  • disableAutoload()可用于在测试替身类的生成期间禁用 __autoload()

然后分别设置两个方法的参数和返回值。这里 insert 操作比较简单,可以用 willReturn($value) 返回简单值:

上面的例子中,使用了 willReturn($value) 返回简单值。这个简短的语法相当于 will($this->returnValue($value))。而在这个长点的语法中,可以使用变量,从而实现更复杂的上桩行为。我们这里的需求是需要根据预定义的参数清单来返回不同的值,显然这是一个映射(map),PHPUnit 提供现成的 returnValueMap() 方法来做这个事情:

完整的单测代码: Continue Reading...

【译】简单介绍通过Predis库在PHP中使用Redis

本文翻译自 《An Introduction to Redis in PHP using Predis》,已得到作者 @Daniel Gafitescu 的允许。原文版权归作者和 sitepoint.com 所有,如果你有原文使用需求请自行联系作者。

Redis 是一个开源的内存数据库服务器,得益于内建的数据类型,Redis 不仅仅只能做简单的 key/value 存储。

Redis 由 @Salvatore Sanfilippo 在 2009 年发布,因为其受欢迎和增长迅速,被很多大公司比如 VMware(后来聘请作者去全职工作)、GitHub、Craigslist、Disqus、Digg、Blizzard、Instagram 等(详见:redis.io/topics/whos-using-redis)使用。

你可以使用 Redis 做会话(session)处理程序,当你使用负载均衡的分布式服务时特别有用。Redis 也可以用作发布/订阅系统,很优雅的创建一个在线聊天或者实时订购程序。关于 Redis 的文档,所有的命令以及其它信息都能在项目网站 redis.io 上找到。

一直以来都有 Redis 和 Memcache 哪个更好的争论,文章 as the benchmarks show 显示在相同的基础操作上两者不相上下。Redis 比 Memcache 有更多的特性,比如内存存储、磁盘持久化、原子操作、事务以及不用记录每一次变化到磁盘上而是用服务端的数据结构来代替。

在这篇文章中将介绍如何使用 Predis 库所提供的一部分基础但很有用的 Redis 命令。

容易安装

Redis 容易安装,简明的安装说明发表在产品的下载页。从我个人经验来看,如果你运行在 Ubuntu 上而又没有安装 TCL(只需运行 sudo apt-get install tcl 即可安装)将会报错。一旦 Redis 安装完成,你可以运行服务:

Redis 的网站上显示的有很多语言可用的 Redis 客户端,每种语言都有好几个。对于 PHP 来说有 5 个。在本文中我使用的是 Predis 库,但是你可能也需要作为 PHP 模块编译、安装的 phpredis 扩展

译者注:有些人可能在 Predis 库和 phpredis 扩展中难于选择,但两者在一般场景下相差不大,目前都支持 PHP7。phpredis 扩展在性能上可能有一些优势,而 Predis 库源码更加优雅(适合学习、阅读),支持 PHP 新的语法特征,但文档较少(这也是我翻译这篇文章的主要原因)。还有,Predis 也有扩展支持(但作者好像没精力维护了,目前还不支持 PHP7),用于提高性能和提供一下其它的特性。

如果你向我一样在机器上安装的有 Git,你只需克隆 Predis 仓库。否则你就要下载 ZIP 包然后解压。(译者注:可以使用更加简便的 composer 安装:composer require predis/predis

测试一下,创建一个如下内容的 test.php 文件,测试是否能通过 Predis 连接上运行着的 Redis。

当你运行这个脚本,你应该能如愿的看见(输出)信息:"Successfully connected to Redis"。

译者注:这里可能有点小问题,代码不会按照预期捕获 Redis 连接失败的异常,因为在初始化 Redis 客户端类的时候并没有真正的连接,而是在运行第一个命令时才做连接,所以需要额外运行一下 $redis->connect(); 来触发连接操作。详见:https://github.com/predis/predis/issues/61

使用 Redis

在这个章节你将了解众多 Redis 提供的命令的概况。Memcache 也有相似的命令,如果你熟悉 Memcache,这些列表对你来说看起来都不会陌生。 Continue Reading...

使用七牛云存储加速你的博客

CDN的全称是Content Delivery Network,即内容分发网络。对于它的好处我想大家都知道,但一直以来都只有大公司才用得起。但如今已经有了一些面对中小企业的CDN服务,甚至是免费的。如百度旗下的加速乐(https://su.baidu.com/),安全宝(http://www.anquanbao.com/),而且安全宝还和DNSPod进行了无缝对接,很有吸引力。还有阿里云(https://www.aliyun.com/)开放存储服务 OSS、内容分发网络 CDN。这些都不错,对于个人站长来说质量和价格都能接受。但这些都有一些限制,有些需要备案,有些对个人开发者不是十分友好。

其实对于个人站点来说,只要能加速网站上的静态文件,比如图片、js文件、css文件,网站的访问速度就会大大的提升。像我的网站空间租用的是香港的服务器,ping值基本在45左右,南北互联延迟不是问题,瓶颈在于网页的加载速度(香港的空间一直都是小水管,带宽小)。基于这个需求,七牛云存储(https://www.qiniu.com/)是个不错的选择。每个月有免费的配额,操作又比较简单。它的直接竞争对手又拍云(https://www.upyun.com/)也是个不错的选择。两者都是提供云存储、云处理、云分发的服务。由于七牛云存储后台操作简捷、直接,每个月又有免费的配额,所以个人推荐使用七牛云存储。

说了那么多现在直接进入主题,仅需三部轻松提升博客访问速度。

第一步:注册七牛云

第二步:七牛云后台设置

首先需要建立一个Bucket(空间)。使用镜像加速需要设置为公开空间。

创建一个公开空间

然后空间需要绑定一个七牛云提供的二级域名(可自由设置),如果你的域名已经备案可以使用自己的域名,不过需要一段时间审核才能生效。

绑定域名

最后开启镜像存储功能。

开启镜像加速

这里有几点需要注意: Continue Reading...

外网免费下载学校图书馆各类论文资源(非原创)

后记:最新的教程请参考资讯民大的推文【小贴士】置身校外如何安全访问校内资源。同时推荐学弟、学妹们关注资讯民大,了解更多校园资讯以及各种实用功能(查成绩、课表等)。

寒假期间想写论文?该怎么样通过校外网来免费下载学校图书馆的各类资源呢?下面为大家简单的介绍下,学校的系统改进了,现在通过外网(非校园网)同样可以免费下载图书馆的全部资源了。主要使用vpn校外访问系统。

第一步:

使用IE浏览器打开 https://vpn.scuec.edu.cn/ 进入中南民族大学vpn系统。提示访问时可能会看到如下提示,点击“继续浏览此网站”即可,至于为什么会有这个警告请参考https://www.williamlong.info/archives/3461.html

证书警告

第二步登录:

进去后的界面:

vpn登陆界面

右边的其它登陆方式想研究的同学可以看一下,我们直接在左边输入用户名和密码登陆(用户名、密码同教务系统/学生门户的用户名、密码)。 Continue Reading...

win8安装校园网客户端(Edu Supplicant)

是前言的后记(2015-10):下面说的教程Windows 8.1同样适用,Windows 10也可以类似的方法解决。不过这些都已经成为历史了,现在学校早已经是VPN拨号(自带全平台兼容属性)了,插上网线就能自动获得ip,然后使用学号和密码拨号就行。使用路由器就更简单了,现在的“智能”路由器基本都支持VPN拨号,而且和网络中心的老师聊过,学校也没有明面上禁止,因为学校根本就不靠这点网费赚钱(学校钱多就是任性,现在都支持免费申请虚拟机了)。不过风险也有,若是别人用你网做一些“和谐”的事情,因为拨号的学号是你的,到时候“查水表第一个找的就是你(校园网一抓一个准,学校这么好的条件,还是多做点更有意义的事情吧)。

最近有人找我重装系统(好男人,重装系统从不收费),问其原因,她说是win8无法安装校园网客户端。自己装了用不了,网络中心也贴出告示说校园网客户端不兼容win8。她拿到售后去装系统却被告知要收费300(售后真是黑啊,我要是收费30早就发家致富了)。本着不到黄河心不死的精神我决定尝试一下在win8上安装校园网的客户端。在失败N次后得出了正确的安装方法:

在桌面下,右键点击右下角网络图标,打开网络和共享中心。

打开网络和共享中心

点击左侧的更改适配器设置,在弹出的窗口中右键打开以太网(若是外接网卡可能不叫以太网)的属性。

以太网属性

更改ipv4属性。按照学校分配的ip地址进行设置(备用DNS服务器地址填写谷歌的DNS服务地址8.8.8.8能有效解决校园网有时无法打开微博等网页的情况)。

ip地址设置

修改保存后,就会弹出网络中心的一个上网须知,下载64位的操作系统。如未弹出下载页面请自行下载,下载地址:http://172.16.0.2/ATclient64.exe (校园网)备用下载地址:https://yun.baidu.com/share/link?shareid=2067345420&uk=3374112987

上网须知

然后需要重启到【禁用驱动程序强制签名】模式下安装校园网客户端。

按win+i键,选择更改电脑设置。

更改电脑设置

点击左侧的常规面板,在右侧最下部选择【立即重启】。 Continue Reading...

windows上安装ruby

其实我不是为了学习ruby而去安装ruby,而是用到有些东西的时候它要使用到ruby的文件组织包gem。就是万恶的gem install。

首先就是要安装ruby,这没什么好说的下载安装就ok了,只是安装的过程中记住选择将ruby添加到系统环境变量中就ok了。下载地址https://rubyinstaller.org/downloads/

现在貌似就安装完了,但其实才刚刚开始而已。

安装后你会发现有时gem install某个程序是还是会报错:“Please update your PATH to include build tools or download the DevKit……”这其实是没有安装DEVELOPMENT KIT的缘故。(参考:https://stackoverflow.com/questions/10694997/gem-install-json-v-1-7-3-gives-please-update-your-path-to-include-build-tools ) 在下载安装ruby的那个网站上下载DEVELOPMENT KIT包,解压,然后cd到解压的目录。依次执行:

提示完成了就OK了。

至此ruby算是安装完成了,然后就可以gem install rails下载rails或者其它需要的程序了。

Y470加装SSD教程以及SSD优化建议

Y470,小Y,2011年的联想性价比较高的游戏影音本,虽然它的下一代y480,y400已经发售。但时至今日(2013.3)还没有停产。i5二代cpu,4G内存,2G的独立显卡,出色之处就在于显存2G的显卡,到目前为止还没有什么带不动的游戏。而它的音响系统也很出色。然而硬盘一直是笔记本的短板(从windows体验指数就能很容易看出),与其无脑的扩充内存还不如换个固态硬盘。

固态硬盘经过2012年的大跌今年开始上涨,不过各种新品频出,各个公司开始加入SSD阵营。(话说内存也涨了很多,12年双十一100块买了一根金士顿4G ddr3内存条,现在涨了几乎一倍价格直逼200)所以有需求的尽快出手吧,不要在等了。 Continue Reading...