aGVsbG8gd29ybGQ=
post @ 2019-06-08

走近Python的加解密

相关概念

数据加密技术

所谓数据加密(Data Encryption)技术是指将一个信息(或称明文,plain text)经过加密钥匙(Encryption key)及加密函数转换,变成无意义的密文(cipher text),而接收方则将此密文经过解密函数、解密钥匙(Decryption key)还原成明文。 ——以上内容节选自【百度百科)】

信息编解码技术

编码是信息从一种形式或格式转换为另一种形式的过程,也称为计算机编程语言的代码简称编码。用预先规定的方法将文字、数字或其它对象编成数码,或将信息、数据转换成规定的电脉冲信号。编码在电子计算机电视、遥控和通讯等方面广泛使用。编码是信息从一种形式或格式转换为另一种形式的过程。解码,是编码的逆过程。——以上内容节选自 【百度百科)】

从以上定义可以总结如下:

  • 数据加密和信息编码都会对原有数据进行一定的转换
  • 两者进行转换的目的是不同的:
    • 数据加密技术更多的出于信息安全的考量
    • 数据的编解码更多的出于计算机传输和存储和解析的考量

因此我们平时在工作交流和表达过程中所说的“Base64加密”其实并非加密,而只是为了某种传输需要将数据明文进行了某种转换。转换的编解码规则是公开的,理论上,任何了解Base64编解码规则的同学,都可以将Base64编码串解码后得到原有数据!

消息摘要算法

消息摘要算法的主要特征是加密过程不需要密钥,并且经过加密的数据无法被解密,目前可以被解密逆向的只有CRC32算法,只有输入相同的明文数据经过相同的消息摘要算法才能得到相同的密文。消息摘要算法不存在密钥的管理与分发问题,适合于分布式网络上使用。——以上内容节选自【百度百科)】

在实际工作中我们常用的信息摘要算法有MD5SHA1

后端开发童鞋经常提到:用户密码不可以明文保存,要使用MD5算法对用户密码进行”加密”后再存至数据库。

同样,这里”加密”也并非我们严格定义上的”加密”,使用MD5处理的原因是信息摘要过程是不可逆,且中间不需要任何密钥的参与!理论上攻击者无法通过信息摘要算法得到结果反推出原始数据,这个特性使得信息摘要算法的主要用途是:

  • 验证数据的完整性和一致性

  • 对数据进行签名及校验

在了解了有关概念和定义后,我们就可以进一步探讨数据加密技术了。

数据加密算法根据加密和解密时是否使用同一密钥可分为

  • 对称加密算法:在加密和解密时使用的是同一个密钥

    常见对称加密算法有:DES算法(安全性上不如AES,逐步被AES替代), AES算法

  • 非对称加密算法:在加密和解密时使用不同密钥

    常见的非对称算法:RSA算法,椭圆曲线算法(又称ECC,被广泛用于区块链业务中,被视为RSA算法的有力挑战者)

本文以当前企业应用中最为常见的AES算法和RSA算法进行介绍,相关代码可在我的github repo中找到

AES加解密算法

流程

AES加解密的流程,先以我看到的一张图描述(如有侵权,请联系博主删除)

AES简介更多有关AES数学原理介绍及算法实现,可参考这篇文章(上述加密流程图即出自此文)

相关概念

  • 密钥

    密钥是AES算法实现加密和解密的根本。对称加密算法之所以对称,是因为这类算法对明文的加密和解密需要使用同一个密钥

    AES支持三种长度的密钥:128位,192位,256位

    如果对于密钥没有一个直观印象,可以将密钥理解为发送方和传输方共同拥有的钥匙。

  • 填充

    要想了解填充,先要了解AES的分组加密特性

    分组加密

    AES算法在对明文加密的时候,并不是把整个明文一股脑加密成一整段密文,而是把明文拆分成一个个独立的明文块,每一个明文块长度128bit。假如一段明文长度是196bit,如果按每128bit一个明文块来拆分的话,第二个明文块只有64bit,不足128bit,这个时候就需要对明文块进行填充。根据填充算法的不同有以下几种常见的填充方式:

    • PKCS#7Padding:假设数据长度需要填充n(n>0)个字节才对齐,那么填充n个字节,每个字节都是n;如果数据本身就已经对齐了,则填充一块长度为块大小的数据,每个字节都是块大小
    • ZeroPadding:数据长度不对齐时使用0填充,否则不填
    • PKCS#5Padding:PKCS7Padding的子集,块大小固定为8字节
  • 模式

    AES的工作模式,体现在把明文块加密成密文块的处理过程中。AES加密算法提供了五种不同的工作模式:CBC、ECB、CTR、CFB、OFB

    其中最为常见且推荐使用的便是CBC模式了

    有关AES算法各模式运作原理不是本文重点,如果你想了解更多有关此内容,推荐阅读这两篇:文章1文章2

过程描述

基于此前密钥就是钥匙的假设,可以认为加密过程理解为将数据装进一个带锁的箱子,这个锁只有钥匙(密钥)拥有者才能打开,而相应的解密过程就是使用密钥打开上锁的箱子并取出其中数据

代码

代码参考简书文章,基于pycryptodome使用Python编写

加密流程

加密流程

解密流程

解密流程

以上部分的具体代码可在我的github repo上找到

RSA加解密算法

流程与场景

RSA加解密的流程,先以我看到的一张图描述(如有侵权,请联系博主删除)

RSA工作流程

其中public_key表示公钥,private_key表示私钥。
我们举两个栗子吧

场景1:

Bob要写情书(明文)给Alice,但是Alice希望情书内容不能被人自己父母发现,于是就采用了RSA加密的方式来传递情书。
Alice先用RSA生成了一对密钥(有一个公钥,和一个私钥),Bob拿走公钥对情书A(明文)进行加密,生成情书B(密文)。Alice拿到情书B后,用手上的密钥,破解了B,把B还原为原来的A。这样一来,其他人因为没有私钥,无法查看他们之间的甜言蜜语,只有Alice一个人知道其中的秘密

场景2:

现在Alice要给Bob回情书,告诉他今晚12点村头桥下约会,那么,如何让Bob知道情书真是Alice写的呢?注意,Alice手上有私钥,Bob手上有公钥。这时,Alice把情书用私钥进行签名,带着签名和情书内容一同寄出给Bob,Bob拿着公钥验证签名,发现确实是Alice写的,这样一来,他就完全可以相信情书的内容了。

这里的签名,本质上,是在允许信息内容别第三者发现的情况下,为了让信息接受者可以验证信息的真实性

上述两个场景的总结:

场景一:公钥加密,私钥解密

场景二:私钥签名,公钥验证。

原理及验证

有关RSA算法的数学原理极其验证过程不是本文的重点,此部分内容建议阅读阮一峰老师的博文:

RSA算法原理(一))

RSA算法原理(二))

代码

根据RSA算法的两个不同应用场景,但无论何种场景都需要生成密钥对,这是RSA算法的基础,这里介绍两种生成密钥对的方法:

方法1:使用openSSL工具

1
2
3
4
5
6
# 生成1024位的私钥
openssl genrsa -out rsa_private_key.pem 1024
# 把RSA私钥转换成PKCS8格式
openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out private_key.pem && rm rsa_private_key.pem
# 生成RSA公钥
openssl rsa -in private_key.pem -out public_key.pem -pubout

有关openSSL工具的更多用法可查阅《openssl命令使用》

方法2:通过pycryptodome库自行创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from Crypto.PublicKey import RSA

def create_rsa_key():
"""
生成RSA加解密的公钥和私钥
:return:
"""
key = RSA.generate(1024)
encrypt_key = key.export_key(pkcs=8)
print('encrypted_key: ', encrypt_key)
with open('my_private_rsa_key.pem', 'wb') as f:
f.write(encrypt_key)

with open('my_rsa_public.pem', 'wb') as f:
f.write(key.publickey().export_key())

场景1

加密过程

rsa加密过程

解密过程

rsa解密过程

场景2

签名过程

签名过程

验签过程

验签过程

以上部分的具体代码可在我的github repo上找到

参考列表

AES部分,以下排名不分先后

  1. 漫画:什么是AES算法?)
  2. AES加密的四种模式详解(https://www.cnblogs.com/liangxuehui/p/4651351.html)
  3. AES五种加密模式
  4. python3 AES 加密
  5. AES模式和填充
  6. 三种填充模式的区别(PKCS7Padding/PKCS5Padding/ZeroPadding)
  7. AES加密算法的详细介绍与实现

RSA部分,以下排名不分先后

  1. openssl命令使用
  2. Python RSA 加密
  3. RSA算法原理及其在HTTPS中的应用
  4. RSA(三) 密钥的格式
  5. RSA加密解密算法—编程实战
  6. RSA算法原理(一))
  7. RSA算法原理(二))

结尾

如果你喜欢我的文章,请扫描以下二维码,给我小额赞赏,如果没有特殊声明,赞赏…将用于改善我的个人生活~比如:奶茶,咖啡,酸奶或其它零食~😁
二维码

阅读此文

上一篇的教程中我向大家介绍了如何识别验证码,向自己的邮箱发送邮件等一系列的车技,在这一次的教程中我将以微信小程序注册的Step2,向大家介绍以下内容:

  • 如何根据IMAP协议轮询读取邮箱账户中的邮件
  • 如何模拟请求激活自己的邮箱账户

根据IMAP协议轮询读取邮箱账户中的邮件

IMAP协议简介

IMAP(Internet Mail Access Protocol,Internet邮件访问协议)以前称作交互邮件访问协议(Interactive Mail Access Protocol)。IMAP是斯坦福大学在1986年开发的一种邮件获取协议。它的主要作用是邮件客户端(例如MS Outlook Express)可以通过这种协议从邮件服务器上获取邮件的信息,下载邮件等。当前的权威定义是RFC3501。IMAP协议运行在TCP/IP协议之上,使用的端口是143。它与POP3协议的主要区别是用户可以不用把所有的邮件全部下载,可以通过客户端直接对服务器上的邮件进行操作。

以上内容节选自百度百科,更多有关IMAP协议的细节请自行查阅相关资料,总之我们需要明确的是:我们可以使用IMAP协议去读取自己的邮箱中的邮件

Python IMAPClient库简介

官方文档传送门!!!

IMAPClient的底层基于Python标准库imaplib,但提供了一组更易用更Pythonic更完整的API

IMAPClient相关概念

声明:以下内容皆为个人于官方IMAPClient库中了解到并结合个人理解,并不保证绝对的权威和正确,如有勘误,请及时指出

  1. Message Identifiers

    【消息标识】

    官方解释如下:
    在IMAP邮件传输协议中,每一封邮件信息被整数来定义,这些消息的数字id对于给定的邮件文件夹而言是一定的

    你可以将这里的消息的标识理解为数据库表中的自增主键ID

  2. Message Flags

    【消息标记】

    解释如下:

    对于收件箱中的邮件总是存在一些状态的变化(最近接受、已读、已删除、草稿、已回复等),这些用于描述邮件的读取或收发状态

  3. Folder Name

    【文件夹名】

    解释如下:

    个人登录邮箱时总是会有一些“容器”用于存放我们的分类邮件,如:收件箱,垃圾箱,已删除等,有图有真相

    文件夹截图

IMAPClient库的使用

关于IMAPClient的库的使用,不是本文的重点,建议阅读官方文档,理清概念,总结要点,查看demo,自己编写demo亲试之~博主会将所有代码上传至github中,有需要的童鞋可以自行查看,下面po一个IMAP协议读取邮件的demo截图吧

IMAPClient使用demo

激活你的小程序邮箱账户

在你的可以成功读取自己的激活邮件内容之后,接下来需要干的自然便是激活邮件内容中的链接。这一过程我们仍然可以使用requests库去完成

需要指出的是邮件内容中激活链接的获取,需要自己去解析html信息中的内容,你可以使用任何解析技术手段(XPath,BeautifulSoup)去处理,想必对于成功获取到邮件内容的你,这一定不是什么难题了~

1. 激活过程分析

当你在浏览器中访问邮件中的链接时,最终会被重定向到一个这样的一个地址

1
https://mp.weixin.qq.com/wxopen/wacontractorpage?action=step3&lang=zh_CN&token=532810804

上述地址中的token参数值非常重要,你可以认为这是微信小程序端serve返回的此次激活标识,并且这个参数的值会在后续的表单请求中使用到,因此需要全局妥善保存~

事实上,当你访问过邮件中的激活链接后,再次访问时,链接便已失效,将无法再得到任何正常响应。因此所谓的邮件激活你可以简单理解为直接向邮件内容中的地址发送请求

2. 代码实战

requests库对于重定向过程有一个默认的策略,如果你希望自己定义请求的过程中的全部行为,可以禁用它

1
2
3
4
5
6
7
8
9
10
11
from urllib.parse import parse_qs
import requests
session = requests.Session()

def get_token(activate_url):
rsp1 = session.get(activate_url, allow_redirects=False)
real_url = rsp1.headers['location']
print('real_url: ', real_url)
pr = parse_qs(real_url)
token = pr['token'][0]
print('token: ', token)

是的,你没看错,只需要简单几行代码就可以实现微信小程序的激活邮件激活并拿到全局请求token值了

结语

好啦,今天的第二部分教程就到此为止啦~其实第三部分教程会依赖第二部分教程中的结果,但考虑到阅读量和学习量,将这部分内容分开来介绍了。

在下一次教程中我将带给大家如下内容:

  • 模拟生成中国大陆居民身份证号(请勿用于非法目的!)
  • 向微信小程序serve申请获取短信验证码(请勿用于刷tencent的短信or短信轰炸他人!)
  • 基于IMAP协议轮询邮件列表
  • 异步通知:确认用户的微信个人信息和小程序申请中的填写的个人信息匹配一致

如果你喜欢我的文章,可以考虑buy me a cup of coffie

赞赏

阅读此文

随着微信小程序的功能越来越完善,小程序的应用也越来越广泛,需要小程序开发的个人与公司也越来越多~然而小程序的注册是一个比较麻烦的设计,里面涉及众多的表单交互,这次我会以自己的工作经验来帮助大家一步步实现小程序的注册托管。需要指出的是,托管小程序的注册平台并不意味着可以完全规避小程序的注册规则和限制。

本教程计划按照小程序注册的三步骤分为三部分,在阅读这一系列教程前,假设你和我一样是依托Python平台进行开发,而且对http协议已经有了一个比较深入的认识

在第一部分的教程当中我将教会大家破除以下3个难题:

  • 如何在不自建SMTP服务下拥有“无限”邮箱
  • 如何识别小程序注册时的验证码
  • 让微信像我们的指名的邮箱发送邮件

下面我们就进入小程序注册的step1吧~如下图:

微信小程序注册首页

“无限“邮箱之道

整体介绍

小程序注册平台时的邮箱,将作为小程序的管理员账号登录。

前提
  1. 一个可以使用的域名(不需要备案,因为不是建站)
  2. 一个可供使用并且具有代收功能的SMTP服务邮箱用户
分析过程

经观察不难得出以下结论:

  1. 不能让用户输入自己的邮箱,这将无法管理,也无法处理后续的邮箱激活步骤
  2. 小程序平台不care你的邮箱是否真实“存在”,只要能够按照他所规定的步骤激活(发送请求)即可

想必你和我一样,会首先考虑在自己的服务器上搭建一个自定义域名的SMTP服务。当我提出这种解决方案时,马上被另一个更好的解决方案替代了:使用具有代收功能的SMTP服务代收该域名下的全部邮件即可。

当然搭建一个SMTP服务肯定也是可行的,但如果你和我一样没有搭建SMTP服务的经验,还是建议你使用代收邮件作为解决方案

实现步骤
  1. 首先请以自己的域名注册一个腾讯企业邮箱(如果你对其它平台的企业邮箱比较熟悉也没问题),地址

  2. 开启邮件代收功能(需使用管理员登陆),操作步骤如下:

    管理员登录

    开启邮件转移

在完成上述两步后,那么恭喜你,你的“无限”邮箱就已经具备啦,下面开始处理另外的2个问题

“焰狰马“识别之法

整体介绍

小程序注册时的验证码其实不算复杂,稍稍对http协议或爬虫技术有所了解的人是很容易破解的。我们这里的破解手段就是俗称的OCR(光学文字识别),需要说明的是肯定不是我们自己去做图像处理,然后OCR识别,这里我推荐大家使用斐斐打码平台,易接入,识别率很高,价格也很实在(绝无广告水分!)。在之前公司的爬虫的项目中,我所使用的是阿里的OCR,不过不知出于何种原因各大云服务商的验证码服务全部下架…只剩普通图片文字服务…值得一提的是,小程序验证码识别的原理,也可同样运用于其它简单验证码网站上~

前提
  1. 熟悉http协议
  2. 斐斐打码平台账号
分析过程
  1. 验证码请求过程

透过chrome自带的抓包工具,我们不难发现,验证码的获取接口如下:

验证码抓包

于是我们很自然会在另一个窗口中访问https://mp.weixin.qq.com/wxopen/waverifycode?r=1545052181759

但是当你在另外一个浏览器中打开时会发现得到的验证码和之前的并不一样…起初我以为是参数“r”不同的原因所导致,后来证实并非如此,小程序的注册平台其实是依托session机制来保证注册时的邮箱和验证码处于同一的会话之下,而这个所谓的”r”参数个人猜测是以微秒为单位的UNIX时间戳,拿去一些工具网站验证之后证明我个人的猜想是正确的。

那么现在的问题是如何保证我获取验证码时的请求和我打开首页时的请求在同一会话下呢~想必细心的你其实已经发现我上图中红色方框圈住的set-cookie部分吧~是的,正是如此,小程序的注册平台正是依托sig这个cookie值来验证你填写邮箱等表单时和你获取验证码的请求是否在统一会话之下。好在Python的requests库封装了Session API,可以令你很方便的操作session对象。相关核心示例代码:

1
2
3
4
5
6
s = requests.Session()				
url = 'https://mp.weixin.qq.com/wxopen/waregister?action=step1'
r = s.get(url, headers=HEADERS)
if r.status_code != 200:
raise
sig, captcha = _user_ocr(s)
  1. 验证码的识别过程

    在了解了验证码的请求过程之后,接下来我们就可以进行识别了,我的解决方案是:将验证码图片直接下载下来,然后交由第三方API(斐斐打码)去识别即可。这一过程相对容易,并没有太多可细说的,有关斐斐打码平台的注册和接入不是本教程重点,感兴趣的童鞋可以走这里——传送门

    相关接入代码

    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
    def _user_ocr(session):
    t = time.time()
    r = str(int(t))
    code_url = 'https://mp.weixin.qq.com/wxopen/waverifycode' + '?r=' + r
    code_rsp = session.get(code_url, headers=HEADERS)
    code_content = code_rsp.content
    sig = code_rsp.cookies['sig']
    print('sig: ', sig)

    filename = r + '.png'
    with open(filename, 'wb') as f:
    f.write(code_content)

    sign, asign = _cacu_sign(r)
    data = {'user_id': PD_ID, 'timestamp': r, 'sign': sign, 'predict_type': '30400',
    'asign': asign, 'up_type': 'mt'}
    files = {'img_data': ('img_data', code_content)}
    url = 'http://pred.fateadm.com/api/capreg'
    rsp = requests.post(url, data=data, files=files)
    res = rsp.json()
    try:
    captcha = json.loads(res['RspData'])
    captcha = captcha['result']
    print('验证码:', captcha)
    except Exception:
    return None, None
    else:
    os.remove(filename)
    return sig, captcha

发送邮件到我们指定的邮箱

整体介绍

在以上两部分完成之后,最后一步令小程序发送邮件其实就是抓取一个表达提交接口,想必这对各位同鞋来说不是什么难事,这里也没有太多的内容需要分析,需要的注意的地方仍然是两点:

  1. 仍然要保证你最后提交数据的请求和之前的请求在同一session之下
  2. 需要更改requests的User-Agent头信息来模拟浏览器,否则请求会被微信直接拦截
  3. 需要修改Referer请求头信息,越过微信的referer防盗链检查

相关代码:

1
2
3
4
5
6
7
8
9
def _send_auth_request(session, sig, verifycode):
HEADERS['Referer'] = 'https://mp.weixin.qq.com/wxopen/waregister?action=step1'
url = 'https://mp.weixin.qq.com/wxopen/waregister'
data = {'token': '', 'lang': 'zh_CN', 'f': 'json', 'ajax': 1, 'verifycode': verifycode,
'random': random.random(), 'regtype': 2, 'email': 'ssaaxx@lvpjob.club',
'pwd': '35096a66eb1884db71501a2691680baf'}
print('data: ', data)
r = session.post(url=url, data=data, headers=HEADERS)
print('r: ', r.json())

测试结果如下:

测试结果

收到的邮件如图:

收到邮件

结语

好啦,今天的第一部分教程就到此为止啦,下一次我将为大家带来有关IMAP协议的介绍,读取邮件并激活,敬请期待。如果你喜欢我的文章,可以扫一下这个二维码给我一点鼓励

赞赏

阅读此文

欢迎使用Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub. 好吧,我还是保留原文这段描述吧~接下来就是干货了,需要注意的事本教程环境是在Mac os下完成

配置环境

安装有node.js 和 npm~(你去node官网下载时,肯定都会带有npm吧)

安装有Git

一个github账号

上述工具的安装和使用我不是本教程的重点,如果你对于它们都很陌生,那本教程就不大适合于你了🙁

生成本地Hexo站点

在你安装好了node.js,并且修改了它的镜像源后,就可以真正开始接下来的操作了。(还没修改的赶紧去改改哈,天朝网络原因…我就不解释了)

1.安装Hexo:

1
npm install hexo-cli -g

2.生成一个Hexo站点

1
2
hexo init [website-name] 名字任意, 这里我就使用的是blog, 完整命令是
hexo init blog

你会发现在你的目录下多了这些文件…项目中各文件夹的定义情查阅官网doc,这里选几个重要描述tree

目录名或文件名 作用
source 用于存放你所生成各种原始资源,你如你的帖子
themes 存放你的站点主题及主题配置文件
_config.yml 站点配置文件,部署,安装插件,修改样式时会用

3.安装Hexo所需依赖

1
2
首先 cd blog (你之前生成站点名)
然后执行 npm install

4.本地预览调试

1
hexo s --debug

之后你就可以代开浏览器访问localhost:4000地址预览博客页面,下面帖上一张图吧(已经很漂亮吧,如果你还不满意,后续会介绍如何修改主题)preview

部署到Githup

部署到github之前你需要完成以下几个工作

1.在github上新建一个Repository,仓库名必须为【your_user_name.github.io】写法固定,这样github才会为你提供域名服务

2.安装hexo与github相关联的package

1
npm install hexo-deployer-git --save

3.修改站点配置文件,上文提到过的 _config.yml文件(位置在最下面),格式如下

1
2
3
4
deploy:
type: git
repository: https://github.com/deimo/deimo.github.io.git(我的)
branch: master

4.生成静态页面

1
hexo generate (或hexo g)

如果有报错发生,执行下列操作

1
2
3
npm install hexo-renderer-ejs --save
npm install hexo-renderer-stylus --save
npm install hexo-renderer-marked --save

5.发布到你的github

1
hexo deploy

此时也许会让你输入你的github用户名和密码…当然如果你使用ssh key,那应该不会要求你的用户名和密码

此时就可以在浏览器中访问:https://deimo.github.io,如果有内容显示~那么恭喜你👏

至此~你的github主页就已经搭建好了~让我们庆祝一下🎁

发布新的博文

好吧,这里我就偷懒了…我就直接用生成站点时的原文内容好了…

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

所以每次在你的博文写完后,你的部署操作大致是

1
2
3
hexo clean
hexo generate
hexo deploy

一些其它常用的hexo命令参考,更多请参见Hexo官网

1
2
3
4
5
6
7
hexo new "postName" #新建文章
hexo new page "pageName" #新建页面
hexo generate #生成静态页面至public目录
hexo server #开启预览访问端口(默认端口4000,'ctrl + c'关闭server)
hexo deploy #将.deploy目录部署到GitHub
hexo help #查看帮助
hexo version #查看Hexo的版本

其它参考

1.关于主题themes 当然你也可以知乎上搜索更多关于主题的信息

2.Hexo官网hexo

3.🙏感谢这位大佬的blog,才让我有了此教程,传送门

阅读此文

glances实现服务器资源监控

在这篇文章中我将会传授使用glances10min搭建一个服务器性能实时监控系统的车技~!

准备工作

  1. 什么是glances

glances是一个由python实现的类似tophtop的服务器性能监控工具,区别在于glances提供的信息和可使用的参数更多,具体其中包括信息:

  • CPU 使用率
  • 内存使用情况
  • 内核统计信息和运行队列信息
  • 磁盘 I/O 速度、传输和读/写比率
  • 文件系统中的可用空间
  • 磁盘适配器
  • 网络 I/O 速度、传输和读/写比率
  • 页面空间和页面速度
  • 消耗资源最多的进程
  • 计算机信息和系统资源
  1. 安装glances

    建议安装py2.7.x下的glances,原因是由于在搭建glances的web server环境时py3下的glances的配套bottle框架貌似没有完全兼容(我在我的mac测试未通过)出现字符编码错误

    1
    pip install glances

在命令行中使用glances

安装完成后直接在终端下执行命令

1
glances

如果出现类似这样的画面,那么恭喜你,你的glances工具就算是安装好了

glances运行图

当然glances的用法远不止如此,更多的glances用法及命令行参数释义,请查阅官方的doc

搭建glances实时监控web服务

  1. 安装bottle

    glances的web服务需要和bottle框架配合才能使用,所以需要先安装bottle,同样是建议安装py2.7.x版本

    1
    pip install bottle
  2. 启动glances服务

    1
    glances -w

    此时终端上就会有相应的输出,你可以根据终端提示在浏览器端进行访问,页面如下

    web端的运行截图

服务器上的简单部署

由于bottle也是符合WSGI规范的web应用,所以部署思路和其它WSGI应用如Django,Flask相同:使用nginx作为反向代理将请求转发至glances服务端口即可

  1. 部署前的工作

    • 上文说得全部

    • nginx

    • screen
  2. 开始部署

    i. 进入screen,然后开启glances服务

    1
    2
    screen -S glances	# 新建一个名叫一个[glances]的任务session
    glances -w # 开启glances服务

    然后Ctrl + a, Ctrl + d 将glances任务Detached掉

    ii. 配置nginx

    1)我们肯定不希望自己服务器的信息被别人知道,所以要使用nginx提供的认证功能

    我以自己的实际部署情况为例

    1
    2
    3
    4
    5
    6
    7
    8
    # 请使用带有root身份的用户登录
    cd /etc/nginx/passwd # 进入自己密码文件所在目录
    ➜ htpasswd -c ./auth.txt test # 新建一个test用户
    New password: # 输入密码
    Re-type new password:
    Adding password for user test
    ➜ cat auth.txt # 查看文件信息
    test:$apr1$xQWpR2dM$228RMBelnZn.8o3GPE7E/1

    2)编写nginx配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    server {
    listen 80;
    server_name [your domain];
    auth_basic "Please input password";
    auth_basic_user_file /etc/nginx/passwd/auth.txt;
    location / {
    #include uwsgi_params;
    proxy_pass http://127.0.0.1:61208;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-for $remote_addr;
    }
    }

    3)检查nginx语法然后重启nginx

    1
    2
    sudo nginx -t 
    sudo systemctl restart nginx
  3. 测试

    接下来你就可以测试你的nginx认证和性能监控是否正常运行了

    nginx认证

    认证成功之后就可以看到之前类似本机的web测试页面了,如果出错了,你可以进入screen查看报错原因

    怎么样,有没有觉得很easy呢~😋😋😋

参考列表

  1. 使用资源监控工具 glances
阅读此文
post @ 2018-08-03

CentOS 安装 Docker CE [转载]

本文转载自博主【开始战斗】的文章,并在其原文之上略有修改,转载时请注明原作者 开始战斗出处

准备工作

系统要求

Docker CE 支持 64 位版本 CentOS 7,并且要求内核版本不低于 3.10。 CentOS 7 满足最低内核的要求,但由于内核版本比较低,部分功能(如 overlay2 存储层驱动)无法使用,并且部分功能可能不太稳定。

卸载旧版本

旧版本的 Docker 称为 docker 或者 docker-engine,使用以下命令卸载旧版本:

1
2
3
4
sudo yum remove docker \
docker-common \
docker-selinux \
docker-engine

使用yum 源安装

执行以下命令安装依赖包

1
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

鉴于国内网络问题,强烈建议使用国内源,下面先介绍国内源的使用。

国内源

执行下面的命令添加 yum 软件源:

1
2
3
sudo yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

以上命令会添加稳定版本的 Docker CE yum 源。从 Docker 17.06 开始,edge test 版本的 yum 源也会包含稳定版本的 Docker CE

官方源
1
2
3
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo

如果需要最新版本的 Docker CE 请使用以下命令:

1
2
sudo yum-config-manager --enable docker-ce-edge
sudo yum-config-manager --enable docker-ce-test

安装 Docker CE

更新 yum 软件源缓存,并安装 docker-ce

1
2
sudo yum makecache fast
sudo yum install docker-ce

启动 Docker CE

1
2
sudo systemctl enable docker
sudo systemctl start docker

建立 docker 用户组

默认情况下,docker 命令会使用 Unix socket 与 Docker 引擎通讯。而只有 root 用户和 docker 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 root 用户。因此,更好地做法是将需要使用 docker 的用户加入 docker 用户组

建立docker组:

1
sudo groupadd docker

将当前用户加入 docker

1
sudo usermod -aG docker $USER

镜像加速

鉴于国内网络问题,后续拉取 Docker 镜像十分缓慢,强烈建议安装 Docker 之后配置

配置方法如下(节选自gitbook《Docker——从入门到实践》):

Ubuntu 16.04+、Debian 8+、CentOS 7

对于使用 systemd 的系统,请在 /etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件)

1
2
3
4
5
{
"registry-mirrors": [
"https://registry.docker-cn.com"
]
}

注意,一定要保证该文件符合json规范,否则Docker将不能启动

之后重新启动服务

1
2
sudo systemctl daemon-reload
sudo systemctl restart docker

检查加速器是否生效

配置加速器之后,如果拉取镜像仍然十分缓慢,请手动检查加速器配置是否生效,在命令行执行 docker info,如果从结果中看到了如下内容,说明配置成功

1
2
Registry Mirrors:
https://registry.docker-cn.com/

更多docker学习相关请查阅这里

本文参考

  1. 本文转载自博主【开始战斗】,如有侵权,请联系本人删除
  2. 部分内容参考GitBook《从入门到实践》
阅读此文
post @ 2018-04-16

与后端的爱恨情仇

前言

接上篇——《Android开发从小白到入门再到放弃》

从客户端到后端,从JAVA到Python…往后又该是何去何从…程序设计真的超有意思呢~总会冒出一些让你不明觉厉的新名词~总会有些你从未接触的新鲜玩具

正文

印象中第一次接触后端…是我在大连实习时~那个时候做了一个小屁小屁(20多个API接口,7张表的样子)的android项目…不过麻雀虽小,但也五脏俱全~

第一次嘛…总是痛并快乐着😈…想到我第一次真正意义上与后端对接时(以前使用Bmob API,下载SDK接入直接在本地操作数据表),那真是令人倍感沮丧…就简简单单仨儿接口…却没有一次成功…当然啦~毫无疑问…全是我客户端的问题…💀自然而然…内心产生了一阵阵劝退的声音…不过好在…有一群暖心的朋友…哎,我直接贴图吧

朋友的鼓励

大佬们的鼓励

那个时候我的连POST请求都没能整明白…回到学校后倍受打击…质疑自己是不是不适合干这行…不过朋友,前辈们的鼓励和经验又让我重拾信心~

从哪跌倒,自然就得从哪爬起嘛~那个时候就暗自下定决心,自己也一定要会后端~(大概那个时候,我所理解的后端…也就是简单的API吧…)实习时公司使用的后端技术是php技术栈,据说是世界最好的语言~😵

哇,有点害怕呀…难道我也要去学世界最好的语言并且是宇宙第一的Php~?反复推敲对比后,终于要在java,python,php中做抉择了…其实碍于当时自己的眼界…也仅限于此…老实说,如果那时的我早日体验到ruby和node.js的优雅及强大,也说不定转到ruby或者node去了呢~当然啦,选择python,不仅仅是因为它可以作为一门优秀的服务端脚本语言,更重要的是它对数据处理的强大支持以及在未来人工智能的无限潜力(那个时候是2016年)~

正是如此,我才敲定了python~不过万万没想到的是…日后毕业入职的第一份job将会是Python后端开发工程师~不知是命中注定还是机缘巧合又或许是我的强烈坚持和洞察先机…我毕业之时已是2017年…移动客户端领域已基本成熟~移动客户端领域…貌似很难再对其传统业务做进一步的深化与扩展了…正是基于此种论断…所以待我去到羊城时并没有投递有关Android开发工程师的岗位,而是选择Python!那个时候…我所有Python的学习及编写代码的时间加起来…貌似还不足一个月…😢

有时总会慨叹自己脸实在黑得口怕,在选择和机遇上貌似总是不尽人意…第一家公司…至今还拖欠着我三个月的实习工资…~不过倒也无所谓了,无论如何我都不后悔,从哲学角度来看这世上就从没白费的努力~这样的思维和态度很符合一位科技工作者,而非一个洞察商机的企业家,不是嘛?~难道你能说在牛顿万有引力横空出世以前,那些拿着望远镜看了一辈子星星的科技工作者就是zz?从这点来看,拒绝为互联网申请专利的“互联网之父”蒂姆比起微软帝国的老大盖茨更加值得令人尊敬和敬佩~一个是科学家~一个是企业家~然而事实是…知道盖茨的朋友远比知道蒂姆的多…呜呜呜呜…心塞塞~貌似学术明星在大众知名度里总是无法同娱乐明星相比较吧…不过这也是显而易见的,两者的群众基础本就不在同一数量级上…

回过头继续说说为什么说说选择后端(ps:这里木有轻视各位前端朋友的意思嗷,纯粹是个人心路旅程及个人观点~)对于任何一款成功的互联网产品而言…随着自身的发展,累计的用户和数据逐渐增多…有三个问题会让你如坐针毡:

  1. 我该怎样存储更大的数据量?
  2. 我该怎样更加快速地响应用户的操作?
  3. 我该怎样在同一时刻为更多的用户提供服务(并发)?简而言之就是“更大”,“更快”,“更高”~!

任何一家互联网企业在自己的发展和产品迭代中…其本质无非也是上述问题在不同阶段的解决方案~我们知道早期计算机的主要任务是为了处理数值计算,而随着信息量的迅猛发展,现在计算机的任务更多的是处理的“字符串”,所以如果你有一款基础软件(如操作系统,数据库)…它能将字符串处理的速度提高哪怕万分之一,那么所产生的经济价值和世界影响难以估量…也许今后计算机的任务将是直接处理富媒体信息,好期待那一日的到来…~😍

上述3个问题的产生,首先在学术界催生了数据存储的NoSQL理论,之前的RDBMS(关系型数据库管理系统)理论在更大的数据量前显得力不从心…然后拉开了各个互联网企业之间的距离,最后是带来了一系列的财富和机遇,大数据、数据挖掘、分布式处理,各种概念再次响起并深入人心~基于大数据分析的精准网络个人营销正逐渐成为现实…在这个移动互联网浪潮的发展已过去将半的背景下,“大数据+”概念貌似呼之欲出😎(不过…怎么比…貌似也比不过…势头更猛的…“人工智能”和“区块链”吧😏…)~

最后我想说的是…对于一款未遇到性能瓶颈的产品…任何一名后端工程师都足以胜任,但是在BAT下,那些看似简单的功能和操作…却毫无例外地凝聚着全球无数最顶尖工程师们的智慧和心血…所以拜托各位圈外的亲们…你们在享受程序员构建的自动化世界时,不要再说:不就是在电脑键盘上敲敲嘛…怎么薪资比我高那么多…我特么在xx地方做xx那么辛苦才挣那么点儿…

不过呢~我是个例外~因为,我可能是个假程序员~啊,哈哈哈哈哈~😭😭😭

结尾

如果你喜欢我的文章,请扫描以下二维码,加我微信,并给我小额赞赏,如果没有特殊声明,赞赏…将用于改善我的个人生活~比如:零食等~😁

二维码

阅读此文
post @ 2018-03-29

前言

今天学习并使用了Travis.CI,遇到了不少问题,所幸都一一得到了解决,为了让自己印象深刻,决心写个blog,既可当成是一个问题记录,也可以看作是一个有关travis.ci的教程

什么是CI

CI,英文全称:Continuous Integration,即持续集成。那么什么又是持续集成?

持续集成指的是只要代码有变更,就自动运行构建和测试,反馈运行结果。确保符合预期以后,再将新代码”集成”到主干。

持续集成的好处在于,每次代码的小幅变更,就能看到运行结果,从而不断累积小的变更,而不是在开发周期结束时,一下子合并一大块代码。

本文要介绍的就是大名鼎鼎的Travis CI

Travis CI

Travis CI提供的就是一个持续集成服务,它在开源社区(github)上非常流行,想必你在逛github时会经常看到这样的徽章

Build Status

是的,这就是使用Travis.CI的标志啦,有木有觉得很有逼格呢~

Travis CI的特点

简单易学(学会了之后就是这种感觉呗😏)

高端大气上档次😎

免费!(Travis CI对github上公开的仓库完全免费,对于私有仓库则会收取一定费用,如果你已经付费购买了github的私有仓库,那么就不必再额外支付Travis CI的费用)

Travis CI的使用条件

前面有提到过…Travis CI在开源社区中十分的流行…事实上…Travis CI也只能结合Github去使用

对于免费版Travis CI,它的地址在这里 travis CI 免费版,对于付费版Travis CI,它的地址如下travis CI 付费版

对Travis CI的使用条件总结如下

  • 拥有 GitHub 帐号
  • 该帐号下面有一个项目
  • 该项目里面有可运行的代码
  • 该项目还包含构建或测试脚本

无论是免费版还是付费版,它们的使用方法都是相同的

Travis CI的使用

  1. 使用github账号登录Travis.CI
  2. 选择需要集成CI服务的仓库并激活,如下图所示

选择并激活仓库

  1. 在你项目的根目录下新建一个.travis.yml的文件,该文件指定了travis CI的行为且必须保存在github的仓库中

    一旦仓库中有了新的commit,Travis就会去找这个文件,并执行其中的相关命令,该文件使用YAML文件格式进行描述,不得不多提一句,一旦你的YAML文件格式错误,Travis将无法识别并自动build,报错如下

    解析错误

    这里有一个在线工具可用于检验你.travis.yml文件的格式是否正确。在线检测YAML文件格式

  2. 编写你的.travis.yml文件

    有关该文件的内容,Travis 提供了很多功能,详情请移步官网

    下面就一些简单的内容做一下解释,假设有.travis.yml文件内容如下

    1
    2
    3
    4
    5
    language: python
    sudo: required
    script: true
    before_install: sudo pip install foo
    script: py.test

    上面代码中,设置了四个字段:运行环境是 Python,需要sudo权限,在安装依赖之前需要安装foo模块,然后执行脚本py.test

    Travis的运行流程很简单,任何项目都会经过两个阶段

    1
    2
    install 阶段:	安装依赖
    script 阶段: 运行脚本
  3. 使用Travis.CI登录服务器实现服务的持续集成

    想要实现此功能,需要一定的前提:

    • ssh key
    • ruby 2.0 +
    • 基于某些原因下的科学上网

    在具备上述条件后就可以开始我们的Travis CI与服务器的交互集成了

    首先需要安装一个gem包:travis

    1
    gem install travis

    安装完成后,切换到你仓库根目录,执行

    1
    travis login

    根据提示,输入你刚刚用于travis-ci网站登录的Github账户名及密码。

    做好基本的项目配置之后,我们需要配置持续部署的自动运行脚本。

    首先使用travis encrypt-file命令对你刚刚在开发环境生成的密匙进行加密(这样一来可以放心地将密匙保存在公开的开源项目当中)

    1
    2
    # 此处的--add参数表示自动添加脚本到.travis.yml文件中
    travis encrypt-file ~/.ssh/id_rsa --add

    之后再打开.travis.yml文件,会发现多了一个before_install的钩子

    1
    2
    3
    before_install:
    - openssl aes-256-cbc -K $encrypted_830d3b21a25d_key -iv $encrypted_830d3b21a25d_iv
    -in id_rsa.enc -out ~\/.ssh/id_rsa -d

    Travis 一共提供了7个钩子,总结如下

钩子名称 阶段解释
before_install install 阶段之前执行
before_script script 阶段之前执行
after_failure script 阶段失败时执行
after_success script 阶段成功时执行
before_deploy deploy 步骤之前执行
after_deploy deploy 步骤之后执行
after_script script 阶段之后执行

注意!!!😡😈默认生成的命令可能会在/前面带转义符\,我们不需要这些转义符,手动删掉所有的转义符,否则可能在后面引发莫名的错误 like this

转义错误

在完成上述内容后,我们还需要正确地设置权限和认证,这是为了避免…出现诸如..需要添加ssh key…确认提示…然而travis CI并没有一个交互式环境…错误如下

权限错误

在全部的准备工作都完成后,就可以添加部署脚本了,这里以我自己的Python项目为例,给出我的.travis.yml文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
script:
- ls
after_success:
- ssh ubuntu@139.199.7.86 'cd /www/ynpublaw && git pull && env/bin/pip install -r requirements.txt'
- ci.sh

before_install:
- openssl aes-256-cbc -K $encrypted_fed0778d0d20_key -iv $encrypted_fed0778d0d20_iv
-in id_rsa.enc -out ~/.ssh/id_rsa -d
- chmod 600 ~/.ssh/id_rsa
- echo -e "Host 139.199.7.86\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config

# safelist
branches:
only:
- dev

参考

本文参考如下:
《一点都不高大上,手把手教你使用Travis CI实现持续部署》

《持续集成服务 Travis CI 教程》

阅读此文

Android开发从小白到入门再到放弃

前言:

哪里有什么专业~对于大学专业~我一直以来都比较确信:学啥儿专业都一样,反正到时毕业都找不到工作~ 😬
钱伟长大佬曾言:“我没有专业,国家的需要就是我的专业”~的确,哪里有什么专业呢?时代缺什么,什么就是我的专业~英雄造时势~可惜不可能人人竟是英雄…只有不断跟进~方才能够让自己落于不败之地~互联网行业的日新月异~恰恰需要你去不断学习~

正文:

13年大学入学,是我第一次接触智能手机,不久后才发现原来在手机上就可以实现日常衣食住行需求…于是感慨移动终端的强大…那时就在心里盘算着…要是日后我也能在手机上开发App,那该是一件多么炫酷的事情哇~

也许你会想身为一名程序员的我接触互联网的时间居然那么晚?是的,没有错,受制于家庭背景和传统教育,甚至于我上大学时的报考专业也是传统化工类(无机非金属材料工程)。再后来…随着自己对所学专业的进一步了解…以及对自己所在大学的教育的失望(虽然还拿着微薄的学院奖学金~)…外加两位任课老师的言论~则是令我下定决心~转行IT!~在这里吐槽一下自己对所谓“学生组织”的认识:尽是一些无所事事、浪得虚名、沽名钓誉的无耻之徒~鲜有精英~所以大学四年我没有加入任何一个校园组织~告诉自己:只有无名之人才会去追逐名利~

至今我还记得我的大学物理老师说:男生,没事儿就多去学点英语和编程~线性代数的老师也说过:错过了大航海时代,错过了工业革命时代~我们现在正处于互联网时代,多么美好的时代呀~!这个时代,我们赶上了!~

那时身处大二上…又貌似选修了一门《安卓开发》的课程…是东软的徐铭老师授课~课讲得很好…很吸引人…然而并没有什么卵用…老师也直说…上了我得课,你肯定做不了什么东西…但能评价一个项目的好坏…我只记得那时啥都不懂得我…看着他在命令行使用mysql帅气的样子~在myeclipse上打开…tomcat,演示钓鱼网站原理时的兴奋与懵逼…虽然…那些都只是javaWeb里…基础中的渣渣…但依旧深深吸引了我…于是我果断回图书馆翻阅下android开发相关书籍…嗯,不大懂…只是感觉自己不明就里地照着上面写就能学会了,

于是…我下了一本电子书(书名貌似是《Android从入门到精通》来着?)…上课看,下课看…回宿舍练…没有语言基础的我…只在vc6.0上写过几行c的我…光是开发环境…就折腾了好久…不过也有好处…能让我对android开发环境的搭建遇到的各种问题都能有非常快的解决方案…也熟悉了SDK下各个文件包的意义…那个时候android studio还不像现在这么普遍…操着eclipse的我…也只是感觉这破玩意儿也就比记事本好用点…完全不能体会到它的强大…对它的使用…仅限于记事本水平…当然啦,书上所有代码…全是硬背…背下来…

照着电子书上的代码…敲了一段时间后…觉得一边看电子书,一边操作IDE很不方便…于是上当当上买了自己的第一本android开发书籍——李刚的《疯狂android讲义》。一本全面…但又不知道去总结经验的书…书上大部分内容都是细枝末节的东西…书上的示例代码给人感觉也是不够健壮,不够有示范性…不过作者经历到是挺励志…对我还算是有激励作用…让我算是坚持了下来…现在想来,如果当时自己的入门书籍,选得是郭琳大神的《第一行代码》话,想必我的android开发之路~会顺畅得多…那时电脑配置不佳(因为我是AMD处理器,无法使用intel的硬件加速技术…后来又听说了tensorflow对AMD也不尽友好…)不能使用google自带的x86镜像模拟器…那个ARM和MIPS 架构的模拟器…速度感人~无奈只能使用真机调试…(后来使用了genymotion)即使是eclipse…也觉得速度…不合时宜…

有了《疯狂android讲义》后…我便开始…研究它…没什么技巧…一点点看,一点点敲…进展很慢,很慢…因为代码全靠背…心里觉得恐惧…偌大一本书~我啥时候能读完…一天6小时的学习时间…全拿来处理代码的小瑕疵了…

我觉得这样的学习效率,肯定是有问题的…于是在贴吧…知乎…寻求经验…这才得知,要学android,必先修java…我一开始甚至对此甚是怀疑…觉得没有java语言基础…硬着头皮来…肯定也能行…~后来自然是发现自己…简直愚不可及…~这里也提醒下广大想学习android的童鞋们…想学android,请先修java…

可惜当我意识到这点的时候…大二上…已经过了大半…于是狠补java基础,我也不对此有所隐瞒,我从某位大佬那里拿到了毕向东的JAVA SE视频。说真的,他讲的实在太好太好了!!!(哪怕是到现在…我也会偶尔回头再去看看java语言)而我也确实很用功很用心的看了他的完整视频,当真是收获满满,所获甚丰,应该说就java SE的内容而言,我怕是很难会忘记了,时至今日我也觉得自己的java SE基础是足够足够扎实的!曾经有幸面试过几位java程序员…面向对象解释的一塌糊涂,privatepublic权限模糊不清…甚至可以毫不掩饰夸张地说,从毕向东的视频里所学习到的面向对象思想,再一次的开发了我的智力,改变了我的思维习惯!港真…语言基础真的很重要…我在大连的一家公司实习过一段时间的Android…曾有同事与我探讨问题…我发现那些问题大部分都是由于其对java语言基础及其特点不熟悉造成的…而不是由android SDK带来

有了语言基础,再学起android来~果然事半功倍,原来几个小时也学不明白的东西~现在几十分钟下来~豁然开朗:原来是这么简单的东西~ 就这样…对于android我终于算是入门了~之后在校内我积极地和老师、同学(研究生)参与各种比赛,做一些学生项目~也在大连市有过近两个月的Android实习经历,可以说那个时候的我对于Android程序设计基础该是比较熟悉了~后来的后来我开始前往进阶之路:各种框架的学习与使用~最新系统AP的I特性~设计模式…view适配…动画…RPC…然而~也不知为何…我未能坚持下去…也许是进阶之路过于漫长…也许是自己过于“花心”~我最终抛弃了android客户端,选择了Python后端~

是的,从我开始接触互联网到成为一名合格程序员,这期间全是靠着自己的胡乱摸索和摸爬滚打…直至今日~

欲知后事如何~请看下篇连载~ 😈

结尾:

如果你喜欢我的文章,扫描以下二维码,加我微信,给我小额赞赏

二维码

阅读此文
post @ 2018-02-12

RabbitMQ基础(一)

简介

1. 什么是消息队列

​ 消息(Message)是指在应用间传送的数据。消息可以非常简单,比如只包含文本字符串,也可以更复杂,可能包含嵌入对象。

消息队列(Message Queue)是一种应用间的通信方式,消息发送后可以立即返回,由消息系统来确保消息的可靠传递。消息发布者只管把消息发布到 MQ 中而不用管谁来取,消息使用者只管从 MQ 中取消息而不管是谁发布的。这样发布者和使用者都不用知道对方的存在

2. 为什么需要使用消息队列

​ 以常见的订单系统为例,用户点击【下单】按钮之后的业务逻辑可能包括:扣减库存、生成相应单据、发红包、发短信通知。在业务发展初期这些逻辑可能放在一起同步执行,随着业务的发展订单量增长,需要提升系统服务的性能,这时可以将一些不需要立即生效的操作拆分出来异步执行,比如发放红包、发短信通知等。这种场景下就可以用 MQ ,在下单的主流程(比如扣减库存、生成相应单据)完成之后发送一条消息到 MQ 让主流程快速完结,而由另外的单独线程拉取MQ的消息(或者由 MQ 推送消息),当发现 MQ 中有发红包或发短信之类的消息时,执行相应的业务逻辑。

以上是用于业务解耦的情况,其它常见场景包括最终一致性、广播、错峰流控等等。

3. AMQP协议简介

​ AMQP :Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。

​ AMQP从一开始就设计成为开放标准,以解决众多消息队列需求的拓扑结构问题。凭借开放,任何人都可以执行这一标准,针对标准编码的任何人都可以和任意AMQP供应商提供的MQ服务器进行交互

4. RabbitMQ 特点

​ RabbitMQ 最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。具体特点包括:

  • 可靠性(Reliability)

    RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认。

  • 灵活的路由(Flexible Routing)

    在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ 已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个 Exchange 绑定在一起,也通过插件机制实现自己的 Exchange 。

  • 消息集群(Clustering)

    队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。

  • 多种协议(Multi-protocol)

    RabbitMQ 支持多种消息队列协议,比如 STOMP、MQTT 等等。

  • 多语言客户端(Many Clients)

    RabbitMQ 几乎支持所有常用语言,比如 Java、.NET、Ruby 等等。

  • 管理界面(Management UI)

    RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker 的许多方面。

  • 跟踪机制(Tracing)

    如果消息异常,RabbitMQ 提供了消息跟踪机制,使用者可以找出发生了什么。

  • 插件机制(Plugin System)

    RabbitMQ 提供了许多插件,来从多方面进行扩展,也可以编写自己的插件。

安装

Mac上可以使用brew

1
brew install RabbitMQ

注意在Mac OS 10.12以后,不在允许brew使用Root权限,如果只是单单纯学习使用,可使用官网二进制程序集地址

RabbitMQ的消息通信模型

概述

消息(message)被发布者(publisher)发送给交换机(exchange),交换机常常被比喻成邮局或者邮箱。然后交换机将收到的消息根据路由规则分发给绑定的队列(queue)。最后AMQP代理会将消息投递给订阅了此队列的消费者,或者消费者按照需求自行获取。如下图

rabbitmq消息通信模型

RabbitMQ的相关概念介绍
  1. 生产者和消费者

    生产者:发送消息的程序

    消费者:一个主要等待接收消息的程序

  2. 交换机

    交换机是用来发送消息的AMQP实体。交换机常常被比喻成邮局或者邮箱

    RabbitMQ具有以下几种交换机类型

Name(交换机类型) Default pre-declared names(预声明的默认名称)
Direct exchange(直连交换机) (Empty string) and amq.direct
Fanout exchange(扇型交换机) amq.fanout
Topic exchange(主题交换机) amq.topic
Headers exchange(头交换机) amq.match (and amq.headers in RabbitMQ)
  1. 信道

    有些应用需要与AMQP代理建立多个连接。无论怎样,同时开启多个TCP连接都是不合适的,因为这样做会消耗掉过多的系统资源并且使得防火墙的配置更加困难。AMQP 0-9-1提供了通道(channels)来处理多连接,可以把通道理解成共享一个TCP连接的多个轻量化连接。

    在涉及多线程/进程的应用中,为每个线程/进程开启一个通道(channel)是很常见的,并且这些通道不能被线程/进程共享。

    一个特定通道上的通讯与其他通道上的通讯是完全隔离的,因此每个AMQP方法都需要携带一个通道号,这样客户端就可以指定此方法是为哪个通道准备的

  2. 队列

    队列如同具名邮箱,消息最终到达队列中并等待消费

  3. 虚拟主机

    为了在一个单独的代理上实现多个隔离的环境(用户、用户组、交换机、队列 等),AMQP提供了一个虚拟主机(virtual hosts - vhosts)的概念。这跟Web servers虚拟主机概念非常相似,这为AMQP实体提供了完全隔离的环境。当连接被建立的时候,AMQP客户端来指定使用哪个虚拟主机

参考

本文参考列表如下

  1. 《消息队列之 RabbitMQ》简书地址
  2. 《RabbitMQ 中文文档》Gitbook地址
阅读此文
⬆︎TOP