Leo的技术分享

记录开发的点滴

概述

在使用TCP编写的应用程序和使用UDP编写的应用程序之间存在一些本质差异,其原因在于这两个传输层之间的差别:UDP是无连接不可靠的数据报协议,不同于TCP提供的面向连接的可靠字节流。从资源的角度来看,相对来说UDP套接字开销较小,因为不需要维持网络连接,而且因为无需花费时间来连接连接,所以UDP套接字的速度也较快。
因为UDP提供的是不可靠服务,所以数据可能会丢失。如果数据对于我们来说非常重要,就需要小心编写UDP客户程序,以检查错误并在必要时重传。实际上,UDP套接字在局域网中是非常可靠的。

UDP 客户 / 服务器程序使用的套接字函数
图:UDP 客户 / 服务器程序使用的套接字函数

上图展示了客户与服务器使用UDP套接字进行通信的过程。在UDP套接字程序中,客户不需要与服务器建立连接,而只管直接使用sendto函数给服务器发送数据报。同样的,服务器不需要接受来自客户的连接,而只管调用recvfrom函数,等待来自某个客户的数据到达。

阅读全文 »

本文对windows编程中涉及的一些基本概念作一个简单的概述。

事件驱动

Windows 应用程序基于事件驱动模型,windows应用程序启动后会一直等待事件的发生。
常见的事件包括,键盘某个按键被按下,鼠标单击,窗口按钮被点击,窗口可见,等等。

消息与消息队列

Windows 操作系统使用消息来通知应用程序事件的发生。当一个事件发生时,windows 会为该事件所对应的应用程序发送一条消息,然后,这条消息就被加入到应用程序的消息队列中。
每个应用程序都有属于自己的消息队列,消息队列包含了windows操作系统向该应用程序发送的所有消息。

消息循环

应用程序在一个消息循环里面不断地检查消息队列,如果消息队列里面存在消息,则将其取出来,并交由对应的窗口过程处理。
消息循环的代码如下所示:

1
2
3
4
while(::GetMessage(&msg, 0, 0, 0)) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
阅读全文 »

一、简述

UNIX系统将所有的外部设备都看作一个文件来看待,所有打开的文件都通过文件描述符来引用。文件描述符是一个非负整数,它指向内核中的一个结构体。当打开一个现有文件或创建一个新文件时,内核向进程返回一个文件描述符。而对于一个socket的读写也会有相应的文件描述符,称为socketfd(socket描述符)。
在UNIX系统中,I/O输入操作(例如标准输入或者套接字的输入)通常包含以下两个不同的阶段:

  • 等待数据准备好
  • 从内核向进程复制数据

例如对于套接字的输入,第一步是等待数据从网络中到达,当所等待的数据到达时,数据被复制到内核中的缓冲区。第二步则是把数据从内核缓冲区复制到应用进程的缓冲区。
根据在这两个不同阶段处理的不同,可以将I/O模型划分为以下五种类型:

  • 阻塞式I/O模型
  • 非阻塞式I/O模型
  • I/O复用
  • 信号驱动式I/O
  • 异步I/O

二、I/O模型

阅读全文 »

最近在看RPC的相关的实现,其中google的 gRPC 默认使用 Protocol Buffers 来作为其接口描述语言(IDL,Interface Definition Language)以及使用 Protocol Buffers 实现消息的序列化与反序列化。因此,很有必要对 protocol buffers 作个初步的了解。
下文以 protobuf 来简称 protocol buffer。

安装

由于自己使用的是 Mac OS,因此,这里讲述 Mac OS 下如何安装 protobuf。
可以在以下链接下载最新版本的 protobuf ,下载链接。可以直接下载其源代码,然后进行编译安装。

源代码下载后,进入其目录,然后执行:

1
2
3
4
$ ./configure
$ make
$ make check
$ sudo make install

编译好后,使用以下命令来测试是否已成功安装:

1
2
$ protoc --version
libprotoc 3.2.0

说明已成功安装。

阅读全文 »

简述

TCP是面向连接的协议,TCP把连接作为最基本的抽象。每一条TCP连接唯一地被通信两端的两个端点所确定。那么,TCP连接的端点是什么呢?TCP连接的端点又叫套接字(socket),根据TCP协议的规定,端口号拼接到IP地址即构成了套接字,即

套接字 socket = (IP地址:端口号)

这样一来,TCP连接可以以下式子表示

TCP连接 ::= {socket1, socket2} = {(IP1: port1),(IP2: port2)}

在面向连接通信中,连接的建立和释放是必不可少的过程。TCP连接的建立采用客户服务器方式,主动发起连接建立的应用进程叫做客户,而被动等待连接的应用进程叫做服务器。
本文主要讲述TCP是如何管理连接的建立和连接的释放的。

TCP的连接建立

在这里插入图片描述

图1:三次握手建立TCP连接

阅读全文 »

概述

Redis Sentinel 是用来实现 Redis 高可用的一套解决方案。Redis Sentinel 由两个部分组成:由一个或者多个 Sentinel 实例组成 Sentinel 系统;由一个主 Redis 服务器(master redis)和多个从 Redis 服务器(slave redis)组成主从备份的 Redis 系统。Sentinel 系统本身是一个分布式的系统,它的作用是监视 redis 服务器,在 master redis 下线时,自动将某个 slave redis 上升为新的主服务器。Redis 系统由 master redis 处理客户端的命令请求,slave redis 作为主服务器的备份而存在。Redis Sentinel 的系统架构如图 1 所示。

Redis Sentinel 架构图

图1:Redis Sentinel 架构图

假设某个时刻,原来的 master redis 进入下线状态,Sentinel 系统就会监控到这个 master redis 已下线,接下来,Sentinel 系统就会进行故障转移操作:

阅读全文 »

在ZooKeeper中,节点也称为znode。由于对于程序员来说,对zk的操作主要是对znode的操作,因此,有必要对znode进行深入的了解。
ZooKeeper采用了类似文件系统的的数据模型,其节点构成了一个具有层级关系的树状结构。例如,图1展示了zk节点的层级树状结构。

这里写图片描述
图1:ZooKeeper的层级树状结构

图1中,根节点 / 包含了两个字节点 /module1,/module2,而节点 /module1 又包含了三个字节点 /module1/app1,/module1/app2,/module1/app3。在zk中,节点以绝对路径表示,不存在相对路径,且路径最后不能以 / 结尾(根节点除外)。

阅读全文 »

ZooKeeper的客户端包括Java版本和C语言版本。使用Java版本连接zk的命令以下:

1
bin/zkCli.sh -server ip:port

执行此命令,客户端成功连接上zk,会有类似以下的输出,其中,包括“Welcome to ZooKeeper!”的欢迎语,以及其他一些连接的信息等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
lihaodeMacBook-Pro:bin lihao$ ./zkCli.sh -server 127.0.0.1:2182
Connecting to 127.0.0.1:2182
2016-06-29 07:51:39,679 [myid:] - INFO [main:Environment@100] - Client environment:zookeeper.version=3.4.8--1, built on 02/06/2016 03:18 GMT
2016-06-29 07:51:39,682 [myid:] - INFO [main:Environment@100] - Client environment:host.name=192.168.31.107
2016-06-29 07:51:39,682 [myid:] - INFO [main:Environment@100] - Client environment:java.version=1.8.0_77
2016-06-29 07:51:39,684 [myid:] - INFO [main:Environment@100] - Client environment:java.vendor=Oracle Corporation
……
2016-06-29 07:51:39,686 [myid:] - INFO [main:ZooKeeper@438] - Initiating client connection, connectString=127.0.0.1:2182 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@531d72ca
Welcome to ZooKeeper!
2016-06-29 07:51:39,715 [myid:] - INFO [main-SendThread(127.0.0.1:2182):ClientCnxn$SendThread@1032] - Opening socket connection to server 127.0.0.1/127.0.0.1:2182. Will not attempt to authenticate using SASL (unknown error)
JLine support is enabled
2016-06-29 07:51:39,797 [myid:] - INFO [main-SendThread(127.0.0.1:2182):ClientCnxn$SendThread@876] - Socket connection established to 127.0.0.1/127.0.0.1:2182, initiating session
[zk: 127.0.0.1:2182(CONNECTING) 0] 2016-06-29 07:51:39,830 [myid:] - INFO [main-SendThread(127.0.0.1:2182):ClientCnxn$SendThread@1299] - Session establishment complete on server 127.0.0.1/127.0.0.1:2182, sessionid = 0x155996605050000, negotiated timeout = 30000

WATCHER::

WatchedEvent state:SyncConnected type:None path:null

连接成功后,便可以使用命令与zk服务进行交互。

阅读全文 »

本文讲述如何安装和部署ZooKeeper。

一、系统要求

ZooKeeper可以运行在多种系统平台上面,表1展示了zk支持的系统平台,以及在该平台上是否支持开发环境或者生产环境。

表1:ZooKeeper支持的运行平台

系统 开发环境 生产环境
Linux 支持 支持
Solaris 支持 支持
FreeBSD 支持 支持
Windows 支持 不支持
MacOS 支持 不支持

ZooKeeper是用Java编写的,运行在Java环境上,因此,在部署zk的机器上需要安装Java运行环境。为了正常运行zk,我们需要JRE1.6或者以上的版本。
对于集群模式下的ZooKeeper部署,3个ZooKeeper服务进程是建议的最小进程数量,而且不同的服务进程建议部署在不同的物理机器上面,以减少机器宕机带来的风险,以实现ZooKeeper集群的高可用。
ZooKeeper对于机器的硬件配置没有太大的要求。例如,在Yahoo!内部,ZooKeeper部署的机器其配置通常如下:双核处理器,2GB内存,80GB硬盘。

阅读全文 »

一、简介

ZooKeeper是一个高性能,分布式的,开源分布式应用协调服务。它提供了简单原始的功能,分布式应用可以基于它实现更高级的服务,比如同步,集群管理,命名空间,配置维护等。ZooKeeper使用了我们熟悉的文件树状结构作为自己的数据模型,因此是易于使用的。

我们知道,由于资源竞争等因素的影响,维护分布式服务的正常运行是一项极具挑战的事情。图1形象地说明了道路交通中没有信号灯的指挥协调导致出现交通阻塞混乱的情况出现。对于分布式系统来说,如果没有一个协调者的角色对各个分布式应用进行协调,分布式系统同样会出现一团糟的情况。

这里写图片描述
图1:混乱的交通

ZooKeeper背后的动机则是为了简化分布式应用的开发流程,并提供更加敏捷健壮的方案,以此来协调分布式系统中的各个应用服务。可以使用交通信号灯来形象比喻zk在分布式系统中的作用。

阅读全文 »
0%