2017-05-28 13:37:15    574    0    0

服务器三种并发方式

迭代服务器

在学习TCP/IP协议中,如果不考虑并发,我们所写出来的服务器往往叫做迭代服务器。迭代服务器会依次处理客户端的连接,只要当前连接的任务没有完成,服务器的进程就会一直被占用,直到任务完成后,服务器关闭这个socket,释放连接

看一个迭代服务器的例子,服务器的功能是接收客户端的输入,服务器接受之后原样返回客户端,即回射服务器。迭代服务器C源码

  1. #include <stdio.h>
  2. #include <netinet/in.h>
  3. #include <sys/socket.h>
  4. #define MAXLEN 1024
  5. int main()
  6. {
  7. int server_sockfd = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
  8. struct sockaddr_in server_sockaddr;
  9. server_sockaddr.sin_family = AF_INET;
  10. server_sockaddr.sin_port = htons(1024);
  11. server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  12. bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr));
  13. listen(server_sockfd, 20);
  14. for( ; ; ){
  15. int clnt_sock = accept(server_sockfd, NULL, NULL);
  16. printf("add client\n");
  17. char buf[1024] = {'\0'};
  18. if(read(clnt_sock, buf, 1024) != 0){
  19. printf("read end \n");
  20. fputs(buf, stdout);
  21. write(clnt_sock, buf, 1024);
2017-05-24 01:27:18    955    0    0

C语言编写服务端入门

前言

本文使用C语言编写一个服务器,旨在更好的理解服务端/客户端程序,迭代服务器,并发服务器。这篇文章的例子很简单,就是当客户端连接上服务端之后,服务端给出一个“Hello World”回应。

C/S结构流程图

整个客户端,服务端交互流程可以用下图表示,服务端是优先启动进程并监听某一个端口,并且进程一直阻塞,直到有客户端连接进来,才开始处理客户端连接。

image

服务端

通过流程图可以看出,服务端涉及的Socket函数有socket, bind, listen, accept, read, write, close。使用这7个函数就可以编写出一个简易服务器。

socket函数

为了执行网络I/O,一个进程必须做的第一件事情就是创建一个socket函数,函数原型

  1. # family 表示协议族
  2. # type 表示套接字类型
  3. # protocol 表示传输协议
  4. # 若成功返回非负描述符,若出错返回-1
  5. int socket(int family, int type, int protocol);

这个函数需要传入协议族,套接字类型,传输层协议三个参数。

协议族可以有以下取值

family 说明
AF_INET IPv4协议
AF_INET6 IPv6协议
AF_LOCAL Unix域协议
AF_ROUTE 路由套接字
AF_KEY 密钥套接字

套接字类型可以有以下取值

type 说明
SOCK_STREAM 字节流套接字
SOCK_DGRAM 数据报套接字
SOCK_SEQPACKET 有序分组套接字
SOCK_ROW 原始套接字

传输层协议可以有以下取值

protocol 说明
IPPROTO_TCP TCP传输协议
IPPROTO_UDP UDP传输协议
IPPROTO_SCTP SCTP传输协议

这里我们选择IPv4协议,使用字节流套接字,传输层选择TCP协议,所以第一段代码:

2017-05-16 19:20:11    506    0    0

MySQL事务和隔离级别

前言

想象一个转账的场景,A要向B转账200元,首先会检查A的账户够不够200元,然后执行A的账户减去200元,最后执行B的账户增加200元。这几条语句可以表示成

  1. 1. select money from account where name=A;
  2. 2. update account set money = money - 200 where name = A;
  3. 3. update account set money = money + 200 where name = B;

可以想象一下,如果前2条语句执行成功,第3条语句执行失败,那么这200元就“不翼而飞”。这个时候我们需要引入事务的概念,这三天语句要么都执行成功,只要有一条语句执行失败,则全部回滚。这样才能保证A的钱财不会白白丢失

事务的ACID

事务必须满足ACID特性,这四个特性分别是原子性,一致性,隔离性和持久性

原子性

一个事务必须被视为不可分割的最小工作单元,整个事务中所有操作要么全部提交成功,要么全部失败回滚。对于一个事务来说,不可能只执行其中的一部分,这就是事务的原子性

一致性

事务总是从一个一致性的状态,转移到另一个一致性的状态。在前面的例子中,即使在执行第3条语句的时候系统奔溃了,A也不会白白损失200元,因为事务最终没有提交。所以事务中所做的修改也不会保存到数据库中。

隔离性

通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。针对上面的例子,试想一下,假如A只有500元,如果SQL执行到第2句,A账户减去了200元。但是,这个时候,另一个进程也需要A转账500元,这个时候就需要考虑这个进程看到的是300元还是500元的问题。这一点比较复杂,会引入隔离级别的概念

持久性

一旦事务提交,则其所做的修改会永久保存到数据库中。此时即使系统奔溃,修改的数据也不会丢失。这一点也比较复杂,会引入持久化的真正含义

隔离级别

在MySQL的事务特性中,隔离一直是比较复杂而且难以理解的话题。MySQL一共给我们提供了4中不同的隔离级别。每一种隔离级别都规定了一个事务中所做的修改,哪些在事务内和

2017-04-16 11:22:44    604    0    0

TCP连接的建立和终止

本文将阐述两个主机之间通过TCP协议通信的话需要哪些步骤,以及在建立连接的过程中经历哪些状态。并使用tcpdump工具帮助我们调试TCP应用,使我们掌握TCP如何建立和终止

TCP和UDP

首先的必须说一下TCP和UDP两种传输层协议;UDP是一种不可靠的传输协议,使用UDP协议时候,一个主机直接把一个数据报扔给另一个主机,而不考虑任何丢失的因数;所以UDP协议效率高不可靠。相反,TCP协议被定义为一种可靠传输协议,必须保证数据报一定要传输到对方(如果有意外,也会给出原因),要实现这种保证,就需要三次握手连接,传输数据确认,四次挥手告别,所以TCP协议是一种复杂,可靠的传输协议。

三次握手

当使用TCP协议传输数据时,为了保证数据的可靠传输,必须先建立连接,当建立一个TCP连接时,会发生以下情形
1. 客户端首先发送一个SYN分节,告诉服务器客户端将在连接中发送数据的初始序列号。
2. 服务器接收到客户端的SYN分节,必须发送一个确认(ACK),同时自己也得发送一个SYN分节,他告诉客户端服务器将在同一连接中发送数据的初始分节序列
3. 客户端收到服务器的SYN之后,发送一个ACK确认,三次握手完成

image

四次挥手

当两台主机使用TCP协议传输数据时,任何一方都不能擅自断开连接,否则后果很严重。比如数据接收方擅自断开连接之后,结果数据发送方还有数据需要发送,这样就会导致数据收发的不一致。所以,建立一个TCP协议需要三次握手,同样,断开一个TCP连接需要四次挥手
1. 某个应用进程首先调用close,则该端为主动关闭,该端的TCP发送一个FIN分节,表示数据发送完毕
2. 接收到这个FIN的对端称为被动关闭,这个传递过来的FIN由TCP确认,即发送一个ACK。它的接收也作为一个文件结束符传递给接收端应用进程。
3. 一段时间后,接收这个文件结束符的进程将调用close关闭它的套接字,这导致它的TCP也发送一个FIN
4.主动关闭的一段接收这个FIN并发送一个ACK确认

image

使用tcpdump调试

使用tcpdump命令可以查看指定网卡的数据分组交换情况,这里直接使用nginx实现的服务器,然后客户

2017-04-14 00:31:09    1548    0    0

Socket网络编程入门

引子

从我们熟悉的web应用为例子,先不讨论socket,我们看一下如果两台机器之间要通讯,需要经过哪些步骤。我们看一下服务器回给我们一个简单的"Hi"时,需要经过哪些步骤。

image

服务端:

  1. 服务器的应用层会产生一个Hi字符串
  2. 数据封装后交给传输层
  3. 传输层封装后交给网络层
  4. 网络层数据封装后交给数据链路层
  5. 物理层接收后变成0和1字节流传输到Internet网络中

客户端:

  1. 客户端物理层接收来自服务端的0和1字节流
  2. 数据链路层接收物理层数据并解读数据报
  3. 网络层接收物理层数据并解读数据报
  4. 传输层解读网络层数据并解读数据报
  5. 应用层接收到Hi字符

现实中的网络数据传输远远比这复杂得多,数据必须经过5层协议栈。试想如果让一个开发者从0开始实现这样的一个数据传输,难度可想而知。但是目前从事网络开发的人千千万万,他们是怎么做到的呢,这一切都要归功于Unix操作系统和Socket。因为有了Socket,网络编程变得快速而且简单了很多。

什么是socket

Socket就是操作系统(Unix)为应用进程提供的一个方便操作网络数据收发的api接口,只要你读懂了这一套api接口,就可以把数据从一个主机传输到另一个主机,或者从其他主机接受数据,而不需要知道还有五层协议的复杂性。这就好比我们开发者读取文件的时候,file系列函数就可以轻松的帮我们获取文件的内容,我们不需要知道磁盘的磁头如何转动,如何实现定位读数据等。
下面是操作系统提供的Socket层的位置

image

这个图的上层是应用程序层,比如我们的nginx,apache系列的软件,下层是操作系统层,比如Unix。Socket层位于应用层和传输层之间,上层应用如果想实现网络编程,只需要调用操作系统提供的Socket层提供的api即可。操作系统通过Socket大大简化了网络编程的复杂性,使得从事网络编程的开发人员更加便捷。

Socket相关函数一览

既然知道了Socket是操作系统为我们提供的一层网络编程接口封装,那就可以看一下操作系统给我们留了哪些接口,我们能用这些接口干什么

函数名称 用途 说明
socket 创建套接字
2017-02-22 23:27:42    804    0    0

Hadoop+Hive环境搭建

JDK安装

由于国内城墙的原因,访问官网下载速度有点慢,这里csdn上下来资源。jdk安装包下载地址:

http://download.csdn.net/download/love254443233/9179483

下载下来上传到Linux服务器上,使用rz命令即可,如果没有这个命令,安装rz参照这篇文章

http://blog.csdn.net/kobejayandy/article/details/13291655

  1. 解压jdk-7u79-linux-x64.tar.gz
  1. [root@S140530 ~]# tar zxvf jdk-7u79-linux-x64.tar.gz
  1. 在/root/.bash_profile中添加如下配置
  1. export JAVA_HOME=/root/jdk1.7.0_79
  2. export PATH=$JAVA_HOME/bin:$PATH
  1. 使环境变量生效,执行以下命令
  1. [root@S140530 ~]# source ~/.bash_profile
  1. 安装验证,执行java命令
  1. [root@S140530 ~]# java -version
  2. java version "1.7.0_79"
  3. Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
  4. Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)

Hadoop安装

下载解压

  1. 下载Hadoop2.7.1
  1. wget "http://mirrors.hust.edu.cn/apache/hadoop/common/hadoop-2.7.1/hadoop-2.7.1.tar.gz"
  1. 复制hadoop-2.7.1.tar.gz 到/usr/hadoop目录下
  1. [root@S140530 hadoop]# makedir /usr/hadoop
  2. [root@S140530 hadoop]# cp hadoop-2.7.1.tar.
2016-11-18 00:30:00    183    0    0

什么是索引

要理解MySQL中索引是如何工作的,最简单的办法就是看一本书的“索引”部分,就像给你一本新华字典,然后要你找出“爵”字,具体做法是根据拼音找出j开头的部分,然后再进一步定位到“爵”的页码,从而找出“爵”。MySQL索引的工作原理也一样。

B-Tree索引

当谈论索引的时候,如果没有特别申明,那多半是指B-Tree索引。B-Tree树意味着所有的值都是按顺序存储的,并且每一个叶子页到根的距离相同。在innoDB存储引擎中,抽象可以用以下图表示B-Tree树索引

B-Tree树能够加快访问数据的速度,因为存储引擎不再需要全表扫描获取需要的数据,取而代之的是从数据的根节点开始进行搜索。根节点的槽中存放了指向子节点的指针,存储引擎根据这些指针继续往下寻找,通过比较节点页的值和要查找的值就可以找到合适的指针进入下层节点,最终找到对应的值或者没找到结果。

MySQL中索引例子

假设有一张表的定义如下:

  1. create table people(
  2. last_name varchar(50) not null,
  3. first_name varchar(50) not null,
  4. dob date not null,
  5. gender enum('m', 'f') not null,
  6. key(last_name, first_name, dob)
  7. )

二级索引组织方式

则在B-Tree索引中,因为建立了一个last_name,first_name,dob的索引,注意key申明的索引为二级索引。数据的组织方式可以用以下图表示

特别注意的是,索引对多个值进行排序是按照create table定义语句中的定义索引的顺序来的,如果第一列一样,则排第二列,以此类推。按照这个数据组织方式,B-tree索引适合全键值键值范围键值前缀查找
以下查询都可以使用到索引
1. 查询一个姓名为Allen Cuba并且生日为1960-01-01的人
2. 查询所有姓Allen的人
3. 查询所有以A为开头自行姓名的人; last_name like ‘A%’
4. 查询姓Allen和Balnger之间的

2016-09-11 10:13:56    525    0    0

单块架构

在认识微服务之前,首先认识一下单块架构,很多互联网公司在创业初期都是采用单块架构,单块架构里将应用分成三层,表示层,逻辑层,访问层(数据)。然后部署在同一web容器上。
title
在单体架构里,以上能表示应用的所有代码,公司每个部门的人都在为这个代码仓库贡献代码,久而久之,代码变得非常庞大,笨重。每个部门的工作效率,交付能力变得越来越收到限制。主要表现为:

  1. 维护成本增加
  2. 交付周期长
  3. 新人培养周期长
  4. 技术选型受限制
  5. 扩展性差
  6. 构建全能团队难

为了改变这种现状,目前很多公司在尝试采用微服务去改造。但是,我们也可以得出,在创业初期其实是不适合做微服务的,因为创业初期需要以业务为主,本身业务不复杂的情况下很难拆分。但是,具备一定规模的公司微服务是相当有必要的。

什么是微服务

微服务目前为止很难有一个准确的定义,但是每个实践微服务的开发者目标是一致的。这里引用ThoughtWorks首席科学家——Martin fowler的一句话

微服务是一种架构模式,它倡导将单一应用程序划分成一组小的服务,服务之间相互协调,相互配合,为用户提供最终价值。每个服务运行在独立的进程中,服务与服务之间采用轻量级通信机制相互沟通(通常是基于HTTP的RESTful API)。每个服务都围绕着具体业务进行构建,并且能独立部署到生产环境,类生产环境等。每一个具体的服务而言,可以选择合适的语言和工具进行构建。

单一职责

如果你使用过Linux命令行,比如要找出当前目录下占用空间最多的5个资源

  1. du -s * | sort -nr | sed 5q

可以看到,这段命令行就是将几个常用的指令拼合起来完成任务。同样,在微服务架构中,也是这样的思路。对每个服务而言,我们希望它处理的业务能够单一,也就是说,微服务架构中的每个服务,都是具有业务逻辑的。不同的服务通过”管道”的方式灵活组合,从而构建出庞大的应用。

轻量级通讯

由于微服务化之后,每个微服务内部都可能采用不一样的语言,不一样的框架,所以微服务之间的通信尽量采用和语言无关,平台无关的方式。
title
对于轻量级通信格式而言,我们属性的XML或者JSON,他们的解析和使用基本与语言无关,平台无关。对于

2016-07-10 11:59:46    463    0    0

什么是SPL

SPL是Standard PHP Library(PHP标准库)的缩写。SPL包括以下内容
1. 数据结构
2. 迭代器
3. 基础接口
4. 异常
4. SPL函数
5. 文件处理

SPL数据结构

虽然我们可以使用传统的变量类型来描述数据结构,例如用数组来描述堆栈(Strack)– 然后使用对应的方式 pop 和 push(arraypop()、arraypush()),但你得时刻小心,·因为毕竟它们不是专门用于描述数据结构的 – 一次误操作就有可能破坏该堆栈。现在,有了SPL,就可以实现我们需要的数据结构

双向链表

双向链表的代码使用如下,更多详细信息可以参考:http://php.net/manual/zh/class.spldoublylinkedlist.php

  1. <?php
  2. /**
  3. * 双向链表
  4. */
  5. $obj = new SplDoublyLinkedList();
  6. $obj->push('yongxiong');//插入到顶部
  7. $obj->unshift('hahaha');//插入到底部
  8. $obj->rewind();//把指针指向底部
  9. echo $obj->current();//取出当前元素 hahaha
  10. $obj->next();//把指针指向下一个节点
  11. echo $obj->current();//yongxiong
  12. $obj->prev();//把指针指向上一个节点
  13. echo $obj->current();//hahahaha

注意,栈是双向链表的一个特例(继承双向链表),包括队列也是双向队列的一个特例。栈的代码操作实例,详细的SQL栈讲解:http://php.net/manual/zh/class.splstack.php

  1. <?php
  2. $obj = new SplStack();
  3. $obj->push(0);//进栈 等同于$obj[] = 0
  4. $obj->push(1);//进栈 等同于$obj[] = 1
  5. echo $obj->pop();//出栈 ,输出1

队列

队列也是继承双向链表,队列的代码实例,详细的队列的讲解:http://php.net/manual

2016-04-30 18:11:32    547    0    0

在PHP中应用回调例子

如果对js非常熟悉的话,一定对匿名函数,回调等概念不陌生

  1. $("#username").clcik(function(){
  2. //code
  3. $getJSON('/data.php', {name:name}, function(){
  4. //远程获取数据
  5. });
  6. });

相信写js的人对上面的代码一定不陌生,同样,PHP之道的发起人写的slim框架,也在大量使用类似的语法,比如下面一段slim的代码

  1. $app->get('/', function ($request, $response, $args) {
  2. return $response->write("Hello " . $args['name']);
  3. });

是不是写php跟写jQuery似的,非常有意思,Slim的作者是PHP和JavaScript程序员,同时也是《PHP The Right Way》的作者,相信js工程师也一定非常喜欢这样的语法。

PHP创建闭包

注意,在PHP中,匿名函数(Anonymous functions),也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数。最经常用作回调函数(callback)参数的值。当然,也有其它应用的情况。比如官网一个闭包函数的例子

  1. <?php
  2. echo preg_replace_callback('~-([a-z])~', function ($match) {
  3. return strtoupper($match[1]);
  4. }, 'hello-world');
  5. // 输出 helloWorld

闭包函数也可以作为变量的值来使用。PHP 会自动把此种表达式转换成内置类 Closure 的对象实例。把一个 closure 对象赋值给一个变量的方式与普通变量赋值的语法是一样的,最后也要加上分号:

  1. <?php
  2. $add = function($a, $b){
  3. return $a + $b;
  4. };
  5. echo $add(3,4);//输出7

注意,闭包函数构建了自己个一个作用域,如果需要使用父级作用域中的变量,必须使用use关键字

2/3