Leo的技术分享

记录开发的点滴

概览

之前对 Nginx,WSGI(或者 uWSGI,uwsgi),Flask(或者 Django),这几者的关系一存存在疑惑。通过查阅了些资料,总算把它们的关系理清了。
总括来说,客户端从发送一个 HTTP 请求到 Flask 处理请求,分别经过了 web服务器层,WSGI层,web框架层,这三个层次。不同的层次其作用也不同,下面简要介绍各层的作用。

在这里插入图片描述

图1:web服务器,web框架与 WSGI 的三层关系

阅读全文 »

概述

RPC(Remote Procedure Call,远程过程调用)是一个计算机通信协议,此协议允许进程间通信。简单来说,当机器 A 上的进程调用机器 B 上的进程时,A 上的调用进程被挂起,而 B 上的被调用进程开始执行。调用方可以通过参数将信息传送给被调用方,然后可以通过被调用方传回的结果得到返回。RPC 框架屏蔽了底层传输方式(TCP/UDP)、序列化和反序列化(XML/JSON/二进制)等内容,使用框架只需要知道被调用者的地址和接口就可以了,无须额外地为这些底层内部编程。
目前主流的 RPC 框架有如下几种。

  • Thrift:Facebook 开源的跨语言框架
  • gRPC:Google 基于 HTTP/2 和 Protobuf 的能用框架
  • Avro:Hadoop 的子项目

本文讲述 RPC 的基本原理并以 Thrift 框架为例说明 RPC 的使用。

基本原理

这里写图片描述
图1:客户端与服务器之间的 RPC 通信过程

阅读全文 »

最近在看侯捷的《STL源码剖析》,看到第三章有关 traits 的介绍,被搞得一头雾水,看了半天不知所云。为了彻底了解这个技法的原理,硬着头皮上网查了资料,并结合 Scott Meyers 的 《Effective C++》,总算是把 traits 的原理搞明白了:)

什么是 traits?我们先来看下 C++ 之父的回答:

Think of a trait as a small object whose main purpose is to carry information used by another object or algorithm to determine “policy” or “implementation details”. - Bjarne Stroustrup

在 C++ 中,traits 习惯上总是被实现为 struct ,但它们往往被称为 traits classes。Traits classes 的作用主要是用来为使用者提供类型信息。

阅读全文 »

概述

我们来看 google 对于 gRPC 的定义:

A high performance, open-source universal RPC framework

即 gRPC 是一个开源的高性能通过 RPC 框架。具体来说,它具有以下特点:

  • 使用 protocol buffers 来作为序列化和反序列化,以及接口定义语言 (IDL)
  • 跨语言,跨平台,gRPC支持多种平台和多种语言,这应该是 gRPC 框架最大的优势
  • 易于使用,安装编译环境和运行环境
  • 基于 HTTP/2 ,提供双向传输和认证机制
阅读全文 »

Git 支持在本地仓库进行程序项目的版本管理,这个本地的 git 仓库在程序项目的文件夹内(也就是 “.git” 文件夹内)。随着程序项目的推进,我们会把不同阶段的文件内容加入到这个 git 仓库中。这个仓库由我们直接操控,我们将它称之为“本地 git 仓库”。
除了“本地 git 仓库”外,如果需要与他人共同开发这个程序项目,还需要一个“远程 git 仓库”。程序项目,本地 git 仓库和远程 git 仓库之间的关系如图1所示。
这里写图片描述
图1:程序项目,本地仓库,远程仓库之间的关系

远程 git 仓库并不一定存储在另一台计算机中。很多人知道 git 支持 HTTP/HTTPS,SSH等协议,以允许本地 git 仓库与存在于另一台计算机中的远程 git 仓库之间传送数据。但实际上,远程 git 仓库也可以跟本地 git 仓库处于同一台电脑中,使用本地协议来进行数据的传送。

阅读全文 »

MongoDB是当今非常流行的一款NoSQL数据库,本文介绍如何使用MongoDB的Java驱动来操作MongoDB。
MongoDB图标

一、引入MongoDB Java Driver包

如果需要操作MongoDB的Java项目是一个Maven项目,可以在依赖中加上以下的配置。

1
2
3
4
5
6
7
<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>2.13.2</version>
</dependency>
</dependencies>

或者通过直接下载jar包的方式使用,下载地址:mongo-java-driver-2.13.2.jar
详细的如何引入MongoDB jar包的方法可以参考官方文档

阅读全文 »

Requests是一常用的http请求库,它使用python语言编写,可以方便地发送http请求,以及方便地处理响应结果。

一、安装

1.1 使用pip进行安装

要安装requests,最方便快捷的方法是使用pip进行安装。

pip install requests

如果还没有安装pip,这个链接 Properly Installing Python 详细介绍了在各种平台下如何安装python以及setuptools,pip,virtualenv等常用的python工具,可以参考其中的步骤来进行安装。如果是在Windows平台下使用requests,也可以参考 《Windows下安装Django》 中有关 pip 安装的介绍来安装pip。

1.2 使用源代码安装

可以在github上下载最新的requests的源代码

git clone git://github.com/kennethreitz/requests.git

下载成功后,使用以下命令进行安装

python setup.py install

二、使用

2.1 发送http请求

为了使用requests,需要首先将requests库import进来:

1
import requests

然后,可以使用requests来发送http请求,例如发送get请求:

1
r = requests.get('http://httpbin.org/ip')

执行此行代码,获得一个Response对象r,从r可以获取http请求的响应结果。

如果要发送post请求,则

1
r = requests.post('http://httpbin.org/post', data={'name': 'leo'})
阅读全文 »

本文讲述实现负载均衡的常用算法。

轮询法(Round Robin)

轮询法是负载均衡中最常用的算法,它容易理解也容易实现。
轮询法是指负载均衡服务器(load balancer)将客户端请求按顺序轮流分配到后端服务器上,以达到负载均衡的目的。
假设现在有6个客户端请求,2台后端服务器。当第一个请求到达负载均衡服务器时,负载均衡服务器会将这个请求分派到后端服务器1;当第二个请求到害时,负载均衡服务器会将这个请求分派到后端服务器2。然后第三个请求到达,由于只有两台后端服务器,故请求3会被分派到后端服务器1。依次类推,其示意图如图1所示。

这里写图片描述
图1:轮询法负载均衡

阅读全文 »

概述

文章负载均衡(Load Balancing)学习笔记(一) 讲述了负载均衡的一般性原理,本文继续介绍常见的实现负载均衡的方法。

HTTP重定向

HTTP重定向服务器是一台普通的Web服务器,用户的请求先到达重定向服务器,这台服务器会挑选一台后端服务器的地址(例如使用轮询的方式),并将该地址写入HTTP重定向响应结果中(以响应状态码302返回)返回给用户。用户将根据这个新的地址重新发送请求到选中的服务器上。选中的服务器会处理用户请求,并将结果返回给用户。
HTTP重定向的处理流程如图1所示。

图1:HTTP重定向实现负载均衡

通过重定向服务器的处理,用户请求被分配到不同的后端服务器上进行处理,实现了负载均衡的目的。

优点

HTTP重定向负载均衡的方法实现上比较简单。

缺点

  1. 增加了用户的时延,因为访问请求需要进行两次往返
  2. 重定向服务器没有将后端服务器的负载差异考虑进去,有些后端服务器可能在相当繁忙时仍然接收到较多的请求
  3. 重定向服务器的并发处理能力制约着整个系统的并发处理能力
  4. 如果重定向服务器出现故障,站点就会瘫痪

由于存在这些缺点,HTTP重定向通常都会与其他一种或多种负载均衡技术结合使用。

阅读全文 »

使用Redis的 SETNX 命令可以实现分布式锁,下文介绍其实现方法。

SETNX命令简介

命令格式

SETNX key value

将 key 的值设为 value,当且仅当 key 不存在。
若给定的 key 已经存在,则 SETNX 不做任何动作。
SETNX 是SET if Not eXists的简写。

返回值

返回整数,具体为

  • 1,当 key 的值被设置
  • 0,当 key 的值没被设置

例子

redis> SETNX mykey “hello”
(integer) 1
redis> SETNX mykey “hello”
(integer) 0
redis> GET mykey
“hello”
redis>

使用SETNX实现分布式锁

多个进程执行以下Redis命令:

SETNX lock.foo <current Unix time + lock timeout + 1>

如果 SETNX 返回1,说明该进程获得锁,SETNX将键 lock.foo 的值设置为锁的超时时间(当前时间 + 锁的有效时间)。
如果 SETNX 返回0,说明其他进程已经获得了锁,进程不能进入临界区。进程可以在一个循环中不断地尝试 SETNX 操作,以获得锁。

阅读全文 »
0%