HTTPS 免费申请和续期

缘由

让个人网站从 HTTP 升级为 HTTPS 是对于众多 web 开发者来说是一件很体现逼格的事情,尤其是能获取免费的 SSL 证书。不花钱一分钱,又能把逼装得漂亮,岂不美哉。

作为一个幼体后端开发工程师, 哥只是个在公司打酱油的角色,平日的工作就是写一些简单的 API 。有一天,需求来了,意思是给刚开发了三期的 API 加上 SSL 认证。天啊,幸福来得太突然了。但心想这样如此简单的 API 还需要 SSL 证书。哥没有立刻答应,而且也作不了主,所以机智地把锅甩给了技术主管,但结局是可想而知的。

Let’s Encrypt

没错!写这篇博文的时候,SSL 证书已经安装成功了,但过程却是相当曲折。为了配置好证书花费了数小时,还把原本的工作给耽误了,这样才有了这篇工作记录。

要开启 HTTPS 认证,就必须要从证书授权机构中获取一个证书,证书有收费的也有免费的。Let’s Encrypt 就是其中一个提供免费证书的机构。

ETL 可视化工具调研

什么是ETL

ETL是 Extract,Transform,Load 的是缩写,分别代表数据的抽取,转换和装载,也就是平时很繁琐,但却是数据分析的基础清洗工作。数据抽取指的是将数据从原始数据库中读取出来,原始的数据库既可以是关系型数据库,如 MySQL,PostgreSQL 等,又可以是非关系型数据库(NoSQL),如 MongoDB,Cassandra 等;数据转换是指根据后续的分析需求预先制定的规则对抽取的数据进行计算和转换,最终将异构的数据统一起来;数据装载一般是指将转换好的数据导入到数据仓库中,如 Hive,Amazon Redshift 等大数据仓库工具。总的来说,ETL 任务需要考虑以下四个方面:

  • 数据结构设计
  • 数据质量
  • 数据传输速度
  • 数据安全

而一款优秀的 ETL 可视化工具需要考虑有以下这些方面:

  • 对数据变更的支持
  • 详细的日志
  • 支持各种数据库
  • 容错机制
  • 通知支持
  • 低延迟
  • 可扩展性
  • 准确性

正向代理与反向代理(转)

计算机网络中,代理(proxy)可分为「正向代理」和「反向代理」,比如著名的翻墙软件 「Shadowsocks」就是一款正向代理软件,全世界前1000的高流量网站都在用的 Web 服务器 「Nginx」也作为反向代理服务器,那么两者之间究竟有什么区别?我尝试着用浅显易懂的例子把两个概念解释清楚。

常用的hive日期函数

以下日期函数均基于hive 1.1.0-cdh5.7.1版本。

from_utc_timestamp:将UTC时间转换成指定时区
参数类型:timestamp或者timestamp格式的string
返回值类型:string

1
2
SELECT FROM_UTC_TIMESTAMP(min_deal_time, 'GMT+8') FROM pubdate; -- min_deal_time TIMESTAMP
SELECT FROM_UTC_TIMESTAMP('2016-11-10 16:59:56.0', 'GMT+8'); -- 2016-11-10 16:59:56.0 timstamp格式的string

to_utc_timestamp:将某一时区下的时间转换成UTC时间
参数类型:timestamp或者timestamp格式的string
返回值类型:string

1
2
SELECT TO_UTC_TIMESTAMP(min_comment_time, 'GMT+8') FROM pubdate; -- min_comment_time TIMESTAMP
SELECT TO_UTC_TIMESTAMP('2016-11-10 16:59:56.0', 'GMT+8'); -- 2016-11-10 16:59:56.0 timstamp格式的string

Python字符编码

基本概念

  • 字节:计算机数据存储的基本单元。比如1 Byte = 8 bits。
  • 字符:信息单位,它是各种文字和符号的统称。
  • 字符集:某个范围内字符的集合,比如ASCII有128个字符,GB2312有7445个字符。
  • 字符码:字符集中每个字符的数字编号,比如ASCII有编号0至127。
  • 字符编码:将字符集中的字符码映射为字节流的一种具体实现方案,比如ASCII字符编码规定使用单字节中低位的7bits去编码所有字符。「A -> 65 -> 0X41 -> b’01000001’」
  • 编码(encode):将字符转换成字节流。
  • 解码(decode):将字节流解析为字符。

生产者/消费者模式

概念

生产者消费者问题,也称有限缓冲问题(Bounded-buffer problem)是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。

  • 生产者在缓冲区满时休眠,等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据
  • 消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者

multiprocessing.Pool的进程锁

通常情况下,python标准库中的multiprocessing.Lock对象是不可以作为进程池Pool的参数,这是因为进程锁不能通过pickle序列化。以下提供两种方法允许在多进程使用过程中引入进程锁,解决资源竞争问题。

参数绑定

实例化Manager()和创建Manager.Lock(),但是使用Manager会产生大量的进程,同时所有获取锁和释放锁的请求都会发送给Manager,这样会造成进程资源的消耗。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import multiprocessing
from functools import partial
def main():
iterable = [1, 2, 3, 4, 5]
pool = multiprocessing.Pool()
m = multiprocessing.Manager()
l = m.Lock()
# functool.partial作用是把keywords,args的参数传入到func中后,生成一个新的函数,其实仍然是func函数,只是有部分参数已经代入
# 这里是为了解决pool.map函数只接受一个iterator作为参数,所以需要将iterator和进程锁绑定在一起
func = partial(target, l)
pool.map(func, iterable)
pool.close()
pool.join()

堆排序

堆的定义如下:

  1. 堆是一颗完全二叉树;
  2. 堆中的某个节点的值总是不大于或不小于其孩子节点的值;
  3. 堆中每个节点的子堆都是堆;

当父节点的键值总是大于或者等于任何一个子节点的键值时为最大堆。当父节点的键值总是小于或者等于任何一个子节点的键值时未最小堆。如下图所示,左边为最大堆,右边为最小堆。

heap.jpg

关于图的知识点

图的存储结构

  • 邻接矩阵(稠密矩阵:点少边多的情况)
  • 邻接表 (稀疏矩阵:点多边少的情况)

图的遍历

  • 深度优先
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void DepthFSearch(AdjMGraph G, int v, int visited[], void Visit(char item))
{
int w;
Visit(G.Vertices.list[v]);
visited[v];
w = GetFirstVex(G, v);
/* 寻找当前顶点的邻接顶点 */
while (w != -1)
{
if (!visited[w])
DepthFSearch(G, w, visited, Visit)
/* 若邻接顶点已被访问,则寻找下一个邻接顶点 */
w = GetNextVex(G, v, w);
}
}

快速排序

快速排序(Quicksort) 在平均状况下,排序n个项目要O(nlogn)次比较。在最坏状况下则需要O(n2)次比较,但这种状况并不常见。它在排序效率同为O(nlogn)的几种排序方法中效率最高,因此经常被采用。

算法思想

设数组a中存放了n个数据元素,low为数组的低端下标,high为数组的高端下标,从数组a中任取一个元素(通常取a[low])作为标准,调整数组a中各个元素的位置,使排在标准元素前面的元素的关键字均小于标准元素的关键字,排在标准元素后面的元素的关键字均大于或等于标准元素的关键字。(即标准元素被放在了未来排好序的数组中该标准元素应在的位置)然后,对这两个字数组中的元素分别再进行方法类同的递归快速排序。递归算法的结束条件是high <= low,即上界下表小于或等于下界下标。

|