单独编译添加PHP的pdo_mysql模块

being 发表了文章 • 0 个评论 • 279 次浏览 • 2017-06-14 22:53 • 来自相关话题

原来编译php的时候,没有把pdo_mysql相关的参数带上,安装完后才发现。再重新编译有点费时间,所以决定单独来安装。
 
先找需要的版本,我用的是稳定的版本。要先看看说明,特别是要注意mysql的php的版本
# wget http://pecl.php.net/get/PDO_MYSQL-1.0.2.tgz
# tar xzvf PDO_MYSQL-1.0.2.tgz
# cd PDO_MYSQL-1.0.2
# /usr/local/php/bin/phpize
Configuring for:
PHP Api Version: 20041225
Zend Module Api No: 20060613
Zend Extension Api No: 220060519
# ./configure执行完以后,报如下错误:
checking for mysql_config... not found
configure: error: Cannot find MySQL header files under这个错误表明系统缺省没有找到你的mysql安装目录,因此可以使用这个命令解决:ln -s /usr/local/mysql/bin/mysql_config /usr/bin/mysql_config这样建立了你的实际msyql安装目录和mysql_config命令的管理

经过configure就可以make了

在执行:./configure 时,又出现了一个问题:
checking for PDO includes... checking for PDO includes...
configure: error: Cannot find php_pdo_driver.h.检查的时候,不能找到php_pdo_driver.h,经过检查,发现在读php-config的时候,在读以前的配置。

解决方法:
./configure –with-php-config=/usr/local/php/bin/php-config (根据实际的路径的来指定)在执行./configure --with-php-config=/usr/local/php/bin/php-config,又出现了一个问题:
error: mysql_query missing!?解决方法:
./configure --with-php-config=/opt/php5/bin/php-config --with-pdo-mysql=/usr/local/mysql(根据自己的实际路径,设定编译安装mysql的位置).
make && make install注意pdo_mysql的全路径,我的是:
/usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/pdo_mysql.so

然后在/usr/local/lib/php.ini加上一句:
extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/pdo_mysql.so重新启动apache即可看到已经加载pdo_mysql成功。 查看全部
原来编译php的时候,没有把pdo_mysql相关的参数带上,安装完后才发现。再重新编译有点费时间,所以决定单独来安装。
 
先找需要的版本,我用的是稳定的版本。要先看看说明,特别是要注意mysql的php的版本
# wget http://pecl.php.net/get/PDO_MYSQL-1.0.2.tgz   
# tar xzvf PDO_MYSQL-1.0.2.tgz
# cd PDO_MYSQL-1.0.2
# /usr/local/php/bin/phpize
Configuring for:
PHP Api Version: 20041225
Zend Module Api No: 20060613
Zend Extension Api No: 220060519
# ./configure
执行完以后,报如下错误:
checking for mysql_config... not found  
configure: error: Cannot find MySQL header files under
这个错误表明系统缺省没有找到你的mysql安装目录,因此可以使用这个命令解决:
ln -s /usr/local/mysql/bin/mysql_config /usr/bin/mysql_config
这样建立了你的实际msyql安装目录和mysql_config命令的管理

经过configure就可以make了

在执行:./configure 时,又出现了一个问题:
checking for PDO includes... checking for PDO includes...  
configure: error: Cannot find php_pdo_driver.h.
检查的时候,不能找到php_pdo_driver.h,经过检查,发现在读php-config的时候,在读以前的配置。

解决方法:
./configure –with-php-config=/usr/local/php/bin/php-config (根据实际的路径的来指定)
在执行./configure --with-php-config=/usr/local/php/bin/php-config,又出现了一个问题:
error: mysql_query missing!?
解决方法:
./configure --with-php-config=/opt/php5/bin/php-config --with-pdo-mysql=/usr/local/mysql
(根据自己的实际路径,设定编译安装mysql的位置).
make && make install
注意pdo_mysql的全路径,我的是:
/usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/pdo_mysql.so

然后在/usr/local/lib/php.ini加上一句:
extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/pdo_mysql.so
重新启动apache即可看到已经加载pdo_mysql成功。

Centos6.8下编译安装Apache 2.4.25详细过程

Ansible 发表了文章 • 0 个评论 • 229 次浏览 • 2017-06-02 19:34 • 来自相关话题

一、下载源码安装包# cd /usr/local/src
# wget 'http://mirror.bit.edu.cn/apache//httpd/httpd-2.4.25.tar.gz'
二、解压安装# tar zxf httpd-2.4.25.tar.gz
# cd httpd-2.4.25
# ./configure --prefix=/usr/local/apache --enable-so --enable-rewrite --with-mpm=worker在这过程中报错如下:

checking for chosen layout... Apache
checking for working mkdir -p... yes
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking target system type... x86_64-unknown-linux-gnu
configure: 
configure: Configuring Apache Portable Runtime library...
configure: 
checking for APR... no
configure: error: APR not found.  Please read the documentation.

解决APR not found 过程如下:# cd /usr/local/src
# wget http://archive.apache.org/dist/apr/apr-1.5.2.tar.gz
# tar zxf apr-1.5.2.tar.gz
# ./configure --prefix=/usr/local/apr
# make && make install
在编译apr的的过程中报错如下:

configure: creating ./config.status
config.status: creating Makefile
config.status: creating include/apr.h
config.status: creating build/apr_rules.mk
config.status: creating build/pkg/pkginfo
config.status: creating apr-1-config
config.status: creating apr.pc
config.status: creating test/Makefile
config.status: creating test/internal/Makefile
config.status: creating include/arch/unix/apr_private.h
config.status: executing libtool commands
rm: cannot remove `libtoolT': No such file or directory
config.status: executing default commands

解决方法如下:
在configure里面 RM='$RM  -f'   这里的$RM后面一定有一个空格。 如果后面没有空格,直接连接减号,就依
然会报错。把RM='$RM'改为RM='$RM  -f'
 
接着重新编译Apache:./configure --prefix=/usr/local/apache --enable-so --enable-rewrite --with-mpm=worker --with-apr=/usr/local/apr报错如下:

checking for chosen layout... Apache
checking for working mkdir -p... yes
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking target system type... x86_64-unknown-linux-gnu
configure: 
configure: Configuring Apache Portable Runtime library...
configure: 
checking for APR... yes
  setting CC to "gcc"
  setting CPP to "gcc -E"
  setting CFLAGS to " -g -O2 -pthread"
  setting CPPFLAGS to " -DLINUX -D_REENTRANT -D_GNU_SOURCE"
  setting LDFLAGS to " "
configure: 
configure: Configuring Apache Portable Runtime Utility library...
configure: 
checking for APR-util... no
configure: error: APR-util not found.  Please read the documentation.

解决APR-util not found过程:# wget 'http://archive.apache.org/dist/apr/apr-util-1.5.2.tar.gz'
# tar zxf apr-util-1.5.2.tar.gz
# cd apr-util-1.5.2
# ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr/bin/apr-1-config
# make && make install
编译完成后,我们再次重新编译Apache:# ./configure --prefix=/usr/local/apache --enable-so --enable-rewrite --with-mpm=worker --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-utilenable-so 允许apache支持动态模块 enable-rewrite 支持URL重定向  with-mpm=worker apache进程模型为worker 默认为prefork
 
最后:# make && make install到这编译就算完成了。 查看全部
一、下载源码安装包
# cd /usr/local/src
# wget 'http://mirror.bit.edu.cn/apache//httpd/httpd-2.4.25.tar.gz'

二、解压安装
# tar zxf httpd-2.4.25.tar.gz
# cd httpd-2.4.25
# ./configure --prefix=/usr/local/apache --enable-so --enable-rewrite --with-mpm=worker
在这过程中报错如下:


checking for chosen layout... Apache
checking for working mkdir -p... yes
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking target system type... x86_64-unknown-linux-gnu
configure: 
configure: Configuring Apache Portable Runtime library...
configure: 
checking for APR... no
configure: error: APR not found.  Please read the documentation.


解决APR not found 过程如下
# cd /usr/local/src
# wget http://archive.apache.org/dist/apr/apr-1.5.2.tar.gz
# tar zxf apr-1.5.2.tar.gz
# ./configure --prefix=/usr/local/apr
# make && make install

在编译apr的的过程中报错如下:


configure: creating ./config.status
config.status: creating Makefile
config.status: creating include/apr.h
config.status: creating build/apr_rules.mk
config.status: creating build/pkg/pkginfo
config.status: creating apr-1-config
config.status: creating apr.pc
config.status: creating test/Makefile
config.status: creating test/internal/Makefile
config.status: creating include/arch/unix/apr_private.h
config.status: executing libtool commands
rm: cannot remove `libtoolT': No such file or directory
config.status: executing default commands


解决方法如下
在configure里面 RM='$RM  -f'   这里的$RM后面一定有一个空格。 如果后面没有空格,直接连接减号,就依
然会报错。把RM='$RM'改为RM='$RM  -f'
 
接着重新编译Apache:
./configure --prefix=/usr/local/apache --enable-so --enable-rewrite --with-mpm=worker --with-apr=/usr/local/apr
报错如下:


checking for chosen layout... Apache
checking for working mkdir -p... yes
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking target system type... x86_64-unknown-linux-gnu
configure: 
configure: Configuring Apache Portable Runtime library...
configure: 
checking for APR... yes
  setting CC to "gcc"
  setting CPP to "gcc -E"
  setting CFLAGS to " -g -O2 -pthread"
  setting CPPFLAGS to " -DLINUX -D_REENTRANT -D_GNU_SOURCE"
  setting LDFLAGS to " "
configure: 
configure: Configuring Apache Portable Runtime Utility library...
configure: 
checking for APR-util... no
configure: error: APR-util not found.  Please read the documentation.


解决APR-util not found过程:
# wget 'http://archive.apache.org/dist/apr/apr-util-1.5.2.tar.gz'
# tar zxf apr-util-1.5.2.tar.gz
# cd apr-util-1.5.2
# ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr/bin/apr-1-config
# make && make install

编译完成后,我们再次重新编译Apache
# ./configure --prefix=/usr/local/apache --enable-so --enable-rewrite --with-mpm=worker --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util
enable-so 允许apache支持动态模块 enable-rewrite 支持URL重定向  with-mpm=worker apache进程模型为worker 默认为prefork
 
最后:
# make && make install
到这编译就算完成了。

Sudo本地提权漏洞安全预警

OS小编 发表了文章 • 0 个评论 • 323 次浏览 • 2017-05-31 15:53 • 来自相关话题

linux 系统sudo存在本地提权高危漏洞,本地攻击者可以利用此漏洞提权至root。请检查您所使用的sudo是否在影响范围之内,并及时进行升级。
影响范围

       Centos 5、6、7

       Redhat Enterprise Linux 5、6、7

       Ubuntu 14.04、15.04、16.04、16.10、17.04、17.10

       Debian wheezy、jessie、jessie、sid

       SUSE Linux Enterprise Software Development Kit 12 SP1、SP2

       SUSE Linux Enterprise Server for SAP 12

       SUSE Linux Enterprise Server 12 SP1 、SP2

       SUSE Linux Enterprise Server 12-LTSS

       SUSE Linux Enterprise Desktop 12 SP1 、SP2

       SUSE Linux Enterprise Server for Raspberry Pi 12 SP2

       OpenSuse
 
修复方案

       【CentOS/RHEL】

       yum update

       或 yum install sudo

       【Ubuntu/Debian】

       sudo apt update $ sudo apt upgrade

       或sudo apt-get install sudo

       备注:部分官方版本还未发布可用修复包,请时刻关注,官网发布后UCloud软件源也会在第一时间更新。

       【修复版本】

       1、Centos /Redhat

       Centos /RHEL 7 :1.8.6p7-22.el7_3

       Centos /RHEL 6 :1.8.6p3-28.el6_9

       Centos /RHEL 5 :1.7.2p1-30.el5_11

       2、Ubuntu

       Ubuntu 14.04:1.8.9p5-1ubuntu1.4

       Ubuntu 16.04:1.8.16-0ubuntu1.4

       Ubuntu 16.10:1.8.16-0ubuntu3.2

       Ubuntu 17.04:1.8.19p1-1ubuntu1.1

       3、Debian

       Debian wheezy:1.8.5p2-1+nmu3+deb7u3

       Debian jessie:1.8.10p3-1+deb8u4

       4、SUSE /OpenSuse

       1.8.10p3-2.11.1

       1.8.10p3-10.5.1
 
漏洞详情

       CVE-2017-1000367:当确定tty时,Sudo没有正确解析/ proc / [pid] / stat的内容,本地攻击者可能会使用此方法来覆盖文件系统上的任何文件,从而绕过预期权限或获取root shell。

       sudo版本查看方法:

       Centos /RHEL /SUSE /OpenSuse:rpm -qa|grep sudo

       Ubuntu /Debian:dpkg -l sudo 查看全部
linux 系统sudo存在本地提权高危漏洞,本地攻击者可以利用此漏洞提权至root。请检查您所使用的sudo是否在影响范围之内,并及时进行升级。
影响范围

       Centos 5、6、7

       Redhat Enterprise Linux 5、6、7

       Ubuntu 14.04、15.04、16.04、16.10、17.04、17.10

       Debian wheezy、jessie、jessie、sid

       SUSE Linux Enterprise Software Development Kit 12 SP1、SP2

       SUSE Linux Enterprise Server for SAP 12

       SUSE Linux Enterprise Server 12 SP1 、SP2

       SUSE Linux Enterprise Server 12-LTSS

       SUSE Linux Enterprise Desktop 12 SP1 、SP2

       SUSE Linux Enterprise Server for Raspberry Pi 12 SP2

       OpenSuse
 
修复方案

       【CentOS/RHEL】

       yum update

       或 yum install sudo

       【Ubuntu/Debian】

       sudo apt update $ sudo apt upgrade

       或sudo apt-get install sudo

       备注:部分官方版本还未发布可用修复包,请时刻关注,官网发布后UCloud软件源也会在第一时间更新。

       【修复版本】

       1、Centos /Redhat

       Centos /RHEL 7 :1.8.6p7-22.el7_3

       Centos /RHEL 6 :1.8.6p3-28.el6_9

       Centos /RHEL 5 :1.7.2p1-30.el5_11

       2、Ubuntu

       Ubuntu 14.04:1.8.9p5-1ubuntu1.4

       Ubuntu 16.04:1.8.16-0ubuntu1.4

       Ubuntu 16.10:1.8.16-0ubuntu3.2

       Ubuntu 17.04:1.8.19p1-1ubuntu1.1

       3、Debian

       Debian wheezy:1.8.5p2-1+nmu3+deb7u3

       Debian jessie:1.8.10p3-1+deb8u4

       4、SUSE /OpenSuse

       1.8.10p3-2.11.1

       1.8.10p3-10.5.1
 
漏洞详情

       CVE-2017-1000367:当确定tty时,Sudo没有正确解析/ proc / [pid] / stat的内容,本地攻击者可能会使用此方法来覆盖文件系统上的任何文件,从而绕过预期权限或获取root shell。

       sudo版本查看方法:

       Centos /RHEL /SUSE /OpenSuse:rpm -qa|grep sudo

       Ubuntu /Debian:dpkg -l sudo

通过CM启动Hive报错

koyo 回复了问题 • 2 人关注 • 2 个回复 • 441 次浏览 • 2017-05-25 23:30 • 来自相关话题

图解Git

回复

Geek小A 回复了问题 • 1 人关注 • 1 个回复 • 397 次浏览 • 2017-05-25 11:49 • 来自相关话题

如何列举出git下某个branch下的所有tag名称和注释

采菊篱下 回复了问题 • 2 人关注 • 1 个回复 • 280 次浏览 • 2017-05-17 16:03 • 来自相关话题

Postfix如何是指支持TLS

采菊篱下 回复了问题 • 2 人关注 • 1 个回复 • 360 次浏览 • 2017-05-12 14:01 • 来自相关话题

华尔街见闻:基于腾讯云容器服务的微服务架构实践

图灵之歌 发表了文章 • 1 个评论 • 519 次浏览 • 2017-05-09 12:26 • 来自相关话题

简介
华尔街见闻的运营方上海阿牛信息科技有限公司是全球金融信息服务提供商,每天全平台为近200万用户提供资讯、数据、研究等服务。旗舰产品华尔街见闻APP长期位居各应用市场财经资讯类客户端第1位。由于将重大事件、市场的基本面变化和100多种全球资产价格紧密关联,在金融领域具有极高渗透率。首创的7x24快讯模式已经成为在中文世界理解全球市场的最快来源。也因此,该产品有技术架构复杂,需要高并发承载能力等特性。

背景
•老系统日益臃肿
原先的系统是PHP monolithic架构,功能按模块划分,日积月累,最后模块达到60+个,新人接手项目会拿到一整个系统的代码,以及需要整个系统的配置,而他可能只需要专注开发不到1/10的业务。
•伸缩性
我们的主要业务是即时资讯,资讯具有时效性,网站的访问量会呈现锯齿形分布。当遇到特大新闻如英国退欧、美国大选、法国大选等,我们要能弹性地通过增加服务资源,提高服务的容量。
•容错性
我们希望一个低优先级服务出现问题之后,不影响主要服务;一个主要服务能保证更高的可用性,就算出现问题,也要保证优雅降级。
比如在重大事件发生的时候,我们希望文章API保证不会受到影响。
•单体应用
PHP单体应用在生产环境服务的时候,所有业务都跑在一个程序里,增加了系统的脆弱性,一个隐藏的性能问题,能在服务量激增的时候成为压垮骆驼的一根稻草。
•云服务商成本
由于架构落后于需要,我们不得不用硬件弥补性能上的问题,导致云服务器成本不断增加。
•线上运维
由于没有方便的监控和运维工具,导致排查问题的效率低,使得在系统遇到问题的时候排查困难,耗时过长。
•开发新功能
开发新任务的同时,我们需要修复原有系统的性能问题。

PHP monolithic架构图 

每台服务器部署相同的服务端PHP代码,由PHP-fpm解释执行,通过Nginx进行反向代理。
 
华尔街见闻微服务架构设计

因此,在2016年11月至2017年3月,我们采用微服务架构启动重构,尝试解决一部分上述问题,在伸缩性上能以服务为单位进行拓容,同时,这一设计会在某些方面增大我们的开发成本和运维成本。
•错误排查复杂
很显然,以前在单体应用中能直接登录服务器,查看出错日志,现在错误散落在不同的服务中,为我们的错误排查带来了困难。
•日志源增加
如何把服务的日志收集并分析。
•基础设施增加
每个服务有互相独立的MySQL、Redis,公共服务方面需要高可用的服务发现,调用链路分析,日志收集储存设施等。

技术选型

微服务架构图

 每台服务器上均衡地部署服务,LB接受用户的请求,将请求转发到API gateway,API gateway向服务发现查询具体服务的IP和端口,服务执行完业务逻辑后向上返回数据。

服务框架
我们选择golang作为我们的后端开发语言。
•    golang在性能和开发效率上有很好的平衡,语法上很简单,并发编程简单高效,基础库健全。
•    调试工具强大
自带一些pprof包可以profile当前程序的CPU消耗、内存占用、锁状态、channel阻塞等,非常便利我们定位问题。
•    有一些优秀的微服务框架
我们选用go-micro作为开发框架,里面包含几乎所有微服务组件,并且支持非常好的拓展性,通过接口的设计方式,让我们可以拓展一些自己的组件,如服务发现、传输协议等。
•    golang在华尔街见闻已经有过比较多的应用,工程师使用golang开发几乎0学习成本。

服务拆分
拆分的原则是通过服务功能划分,尽量避免双向依赖。我们拆分出了13个服务,包括用户、内容、实时新闻、评论、搜索、商城、支付、三方代理等服务。

服务间通信
服务间使用protobuf协议对数据进行编码,使用UDP作为传输协议。

服务发现
Etcd搭建多节点高可用的服务发现。

服务保护
我们选择Hystrix作为服务保护以及服务降级的方案。
每个服务开发者,需要定义自己服务接口的并发量、超时时间以及fallback方法。

部署方案

我们选择了Kubernetes。 
* Docker Swarm
这是我们最先选择的方案,因为Docker 1.12之后已经将Swarm功能集成到Docker En-gine,能以最少的配置启动Docker集群。经过简化和设计的控制台API,方便地管理集群、调整服务如控制服务的数量、CPU、内存限制等。往集群内加入机器非常简单,只需要运行一条命令即可。使用manager-worker架构,manager作为调度节点,支持高可用。
但遇到了非常致命的问题,比如频繁更新服务的时候会出现服务访问不到,某服务的负载均衡后挂载的服务IP是其它服务的,服务之间的通信有几率出现超时问题,归根结底,还是社区正在不断完善swarm,有很多不稳定的地方,网络方面没有进行优化。
* Kubernetes
这是谷歌主导的服务编排工具,它支持Docker,相比Docker Swarm来说,它的概念更多,分层更细。功能方面多于Docker Swarm,支持一些高级功能如秘钥管理、配置管理、自动拓容等。在生产环境的应用比较广泛,稳定性更高。
* 裸机部署
裸机部署是我们的一个备案,考虑到以上两个方案在当时没有具体线上实施的经验,所以如果Docker Swarm和Kubernetes都没有成功,我们直接裸机部署。
裸机部署的需要解决单机端口冲突,如果一个服务在一个服务器上最多只部署一个,那么可以通过写脚本,并划分服务器角色的方式进行部署,利用ansible可以定义user服务集群、content服务集群、comment服务集群等,通过分发二进制文件的方式让服务启动,这样的方案要考虑到服务更新、服务重启、服务删除等逻辑,同一时间只有部分节点更新,在服务未更新成功的时候流量暂时不能打到正在更新的节点。

准备工作

代码托管
由于之前使用github开发人员的代码提交在有翻墙工具的帮助下速度依然不是很理想,我们自建了Gitlab仓库,自此开发过上了幸福的生活。

容器化
swarm和kubernetes是基于docker快速创建删除服务,通过增加容器为服务拓容,缩减容器为服务缩小规模,所以所有项目必须要构建docker镜像。按项目类型划分,我们遇到3种镜像打包情况。
1.    后端项目
后端服务90%是golang项目,针对golang的镜像,我们采取将golang项目编译成可执行文件,基于最小的alpine镜像打包入docker,这里遇到过一个问题,就是alpine里缺少openssl的证书,无法支持https,我们自定义了新的基础镜像,不仅将证书文件打入镜像,同时为了线上调试方便,增加了tcpdump、strace、bash等工具,在初期调试容器间通信问题时发挥重要的作用。
2.    前端静态文件
见闻的后台以及m站基于Vue,编译后生成的静态文件打入镜像,通过nginx访问。 为了支持HTTP2,我们打入nginx镜像缺少的证书。
3.    服务端渲染
主站PC站基于nodejs、Vue实现服务端渲染,所以不仅需要依赖nodejs,而且需要利用pm2进行nodejs生命周期的管理。为了加速线上镜像构建的速度,我们利用taobao源https://registry.npm.taobao.org进行加速, 并且将一些常见的npm依赖打入了基础镜像,避免每次都需要重新下载,镜像打包从开始的3分钟缩减到1.5分钟。

三类镜像结构
 

持续集成
我们利用Gitlab CI配置了测试、镜像构建、镜像发布、自动部署等流程,后端服务从提交代码到测试分支到测试环境自动部署完成花费1.5分钟,前端服务平均为2.5分钟。

CI任务中的test->build->docker->deploy流程 


云平台的选择
最终,我们选择了腾讯云的容器服务,主要基于以下几点考虑:
•    腾讯云的容器服务是在腾讯云的Iaas上为每个用户构建容器集群,腾讯云提供的微服务架构和持续集成与交付的应用场景基本满足了我们的述求。
•    腾讯云的容器服务是基于Kubernetes实现的,支持完全的kubernetes能力。
•    腾讯云在Kubernetes上实现了他们的存储、负载均衡等产品的插件、复用了腾讯云本身平台的监控、日志等能力。减少了我们接入和开发的成本。

服务在腾讯云的应用
我们将我们的应用重构成微服务的架构,每个微服务部署成腾讯云容器服务上的一个服务,前端接入通过一个负载均衡。后端服务间可互相访问。
服务器安全方面,内部服务器通过VPC进行网络隔离,将网络划分为生产环境、测试环境,在生产环境中又划分backend子网和data子网,设定子网之间的访问规则。
为了禁止内部服务器的外网访问,不给内部服务器分配外网IP,仅通过跳板机访问。

性能对比
利用locust模拟线上请求的比例,利用2台16核的压测机在内网对10台16C32G的机器上的服务进行压测,达到1w/s QPS以上,并且服务的负载并没达到极限,这已经是之前PHP生产环境20+台16C32G服务器能达到的QPS。


线上调用追踪
通过追踪API调用链的流向与耗时,我们可以找出性能的瓶颈。我们通过zipkin实际优化了几种情况:
•    服务调用冗余
当拉取文章列表的时候,我们需要拉取文章对应的作者信息,开始的时候我们使用拉取单个作者信息的方式,后来性能调优阶段,我们将其改为批量拉取作者列表,减少RPC的冗余。
•    服务耗时长
对于有些本身就比较耗时并且对即时性不是那么苛刻的计算服务,我们为了保证服务的响应时间,会适量地加上缓存。

监控与报警
由从外部系统表征到内部日志,我们将监控分为API健康,程序错误报警,以及服务器/容器负载。
排查问题的流程一般有两种情况,一种是用户发现问题,申报问题,开发人员跟进问题;一种是我们的监控优先发现问题,开发人员在用户反馈前跟进并修复。在报警方面,我们通过为监控系统谨慎设置报警阈值,当触发报警时,开发人员会收到邮件。
这里我们在报警的定义上有过思考,即什么样的报警算是有意义的?我们遇到过每天10几条重复的报警,通常开发人员开始时会对报警非常重视,当重复的报警一再出现,渐渐失去了对报警的关注。所以我们有解除一些不必要的报警,并且对剩余一些报警进行调查,甚至有些警报是因为监控工具本身的不准确引起的。

API健康
我们设置默认的时间区间是5分钟
•    统计API五分钟内平均QPS
•    API 98%以内的延迟分布
•    QPS最高的前10的API
•    API的返回码的分布

程序错误报警
后端程序内接入Sentry日志报警系统,golang程序捕获panic日志以及error日志,并发送报警邮件。

服务器/容器负载
通过在服务器上运行telegraf daemon进程,收集服务器metrics并发送给influxdb,使用Grafana作为前端面板,对服务器负载以及容器的平均CPU、内存占用率进行监控。

结束语
本文介绍了华尔街见闻通过重构和服务容器的重新部署,实践微服务架构的情况。经过几个月的开发测试,我们不仅完成了线上服务从PHP到Golang的转型,更在服务的稳定性上经历了考验,支撑了几次重大新闻的高流量。
在开发流程上,搭建了完善的自动化工具,减少了人工操作的重复性和误操作概率。
在运维方面,由于监控系统对系统完整的监控,与Kubernetes健全的上线、下线、回滚、拓容功能配合,能以极快的速度处理线上问题。 查看全部
简介
华尔街见闻的运营方上海阿牛信息科技有限公司是全球金融信息服务提供商,每天全平台为近200万用户提供资讯、数据、研究等服务。旗舰产品华尔街见闻APP长期位居各应用市场财经资讯类客户端第1位。由于将重大事件、市场的基本面变化和100多种全球资产价格紧密关联,在金融领域具有极高渗透率。首创的7x24快讯模式已经成为在中文世界理解全球市场的最快来源。也因此,该产品有技术架构复杂,需要高并发承载能力等特性。

背景
•老系统日益臃肿
原先的系统是PHP monolithic架构,功能按模块划分,日积月累,最后模块达到60+个,新人接手项目会拿到一整个系统的代码,以及需要整个系统的配置,而他可能只需要专注开发不到1/10的业务。
•伸缩性
我们的主要业务是即时资讯,资讯具有时效性,网站的访问量会呈现锯齿形分布。当遇到特大新闻如英国退欧、美国大选、法国大选等,我们要能弹性地通过增加服务资源,提高服务的容量。
•容错性
我们希望一个低优先级服务出现问题之后,不影响主要服务;一个主要服务能保证更高的可用性,就算出现问题,也要保证优雅降级。
比如在重大事件发生的时候,我们希望文章API保证不会受到影响。
•单体应用
PHP单体应用在生产环境服务的时候,所有业务都跑在一个程序里,增加了系统的脆弱性,一个隐藏的性能问题,能在服务量激增的时候成为压垮骆驼的一根稻草。
•云服务商成本
由于架构落后于需要,我们不得不用硬件弥补性能上的问题,导致云服务器成本不断增加。
•线上运维
由于没有方便的监控和运维工具,导致排查问题的效率低,使得在系统遇到问题的时候排查困难,耗时过长。
•开发新功能
开发新任务的同时,我们需要修复原有系统的性能问题。


PHP monolithic架构图 

每台服务器部署相同的服务端PHP代码,由PHP-fpm解释执行,通过Nginx进行反向代理。
 
华尔街见闻微服务架构设计

因此,在2016年11月至2017年3月,我们采用微服务架构启动重构,尝试解决一部分上述问题,在伸缩性上能以服务为单位进行拓容,同时,这一设计会在某些方面增大我们的开发成本和运维成本。
•错误排查复杂
很显然,以前在单体应用中能直接登录服务器,查看出错日志,现在错误散落在不同的服务中,为我们的错误排查带来了困难。
•日志源增加
如何把服务的日志收集并分析。
•基础设施增加
每个服务有互相独立的MySQL、Redis,公共服务方面需要高可用的服务发现,调用链路分析,日志收集储存设施等。


技术选型

微服务架构图

 每台服务器上均衡地部署服务,LB接受用户的请求,将请求转发到API gateway,API gateway向服务发现查询具体服务的IP和端口,服务执行完业务逻辑后向上返回数据。

服务框架
我们选择golang作为我们的后端开发语言。
•    golang在性能和开发效率上有很好的平衡,语法上很简单,并发编程简单高效,基础库健全。
•    调试工具强大
自带一些pprof包可以profile当前程序的CPU消耗、内存占用、锁状态、channel阻塞等,非常便利我们定位问题。
•    有一些优秀的微服务框架
我们选用go-micro作为开发框架,里面包含几乎所有微服务组件,并且支持非常好的拓展性,通过接口的设计方式,让我们可以拓展一些自己的组件,如服务发现、传输协议等。
•    golang在华尔街见闻已经有过比较多的应用,工程师使用golang开发几乎0学习成本。

服务拆分
拆分的原则是通过服务功能划分,尽量避免双向依赖。我们拆分出了13个服务,包括用户、内容、实时新闻、评论、搜索、商城、支付、三方代理等服务。

服务间通信
服务间使用protobuf协议对数据进行编码,使用UDP作为传输协议。

服务发现
Etcd搭建多节点高可用的服务发现。

服务保护
我们选择Hystrix作为服务保护以及服务降级的方案。
每个服务开发者,需要定义自己服务接口的并发量、超时时间以及fallback方法。


部署方案

我们选择了Kubernetes。 
* Docker Swarm
这是我们最先选择的方案,因为Docker 1.12之后已经将Swarm功能集成到Docker En-gine,能以最少的配置启动Docker集群。经过简化和设计的控制台API,方便地管理集群、调整服务如控制服务的数量、CPU、内存限制等。往集群内加入机器非常简单,只需要运行一条命令即可。使用manager-worker架构,manager作为调度节点,支持高可用。
但遇到了非常致命的问题,比如频繁更新服务的时候会出现服务访问不到,某服务的负载均衡后挂载的服务IP是其它服务的,服务之间的通信有几率出现超时问题,归根结底,还是社区正在不断完善swarm,有很多不稳定的地方,网络方面没有进行优化。
* Kubernetes
这是谷歌主导的服务编排工具,它支持Docker,相比Docker Swarm来说,它的概念更多,分层更细。功能方面多于Docker Swarm,支持一些高级功能如秘钥管理、配置管理、自动拓容等。在生产环境的应用比较广泛,稳定性更高。
* 裸机部署
裸机部署是我们的一个备案,考虑到以上两个方案在当时没有具体线上实施的经验,所以如果Docker Swarm和Kubernetes都没有成功,我们直接裸机部署。
裸机部署的需要解决单机端口冲突,如果一个服务在一个服务器上最多只部署一个,那么可以通过写脚本,并划分服务器角色的方式进行部署,利用ansible可以定义user服务集群、content服务集群、comment服务集群等,通过分发二进制文件的方式让服务启动,这样的方案要考虑到服务更新、服务重启、服务删除等逻辑,同一时间只有部分节点更新,在服务未更新成功的时候流量暂时不能打到正在更新的节点。

准备工作

代码托管
由于之前使用github开发人员的代码提交在有翻墙工具的帮助下速度依然不是很理想,我们自建了Gitlab仓库,自此开发过上了幸福的生活。

容器化
swarm和kubernetes是基于docker快速创建删除服务,通过增加容器为服务拓容,缩减容器为服务缩小规模,所以所有项目必须要构建docker镜像。按项目类型划分,我们遇到3种镜像打包情况。
1.    后端项目
后端服务90%是golang项目,针对golang的镜像,我们采取将golang项目编译成可执行文件,基于最小的alpine镜像打包入docker,这里遇到过一个问题,就是alpine里缺少openssl的证书,无法支持https,我们自定义了新的基础镜像,不仅将证书文件打入镜像,同时为了线上调试方便,增加了tcpdump、strace、bash等工具,在初期调试容器间通信问题时发挥重要的作用。
2.    前端静态文件
见闻的后台以及m站基于Vue,编译后生成的静态文件打入镜像,通过nginx访问。 为了支持HTTP2,我们打入nginx镜像缺少的证书。
3.    服务端渲染
主站PC站基于nodejs、Vue实现服务端渲染,所以不仅需要依赖nodejs,而且需要利用pm2进行nodejs生命周期的管理。为了加速线上镜像构建的速度,我们利用taobao源https://registry.npm.taobao.org进行加速, 并且将一些常见的npm依赖打入了基础镜像,避免每次都需要重新下载,镜像打包从开始的3分钟缩减到1.5分钟。

三类镜像结构
 

持续集成
我们利用Gitlab CI配置了测试、镜像构建、镜像发布、自动部署等流程,后端服务从提交代码到测试分支到测试环境自动部署完成花费1.5分钟,前端服务平均为2.5分钟。

CI任务中的test->build->docker->deploy流程 


云平台的选择
最终,我们选择了腾讯云的容器服务,主要基于以下几点考虑:
•    腾讯云的容器服务是在腾讯云的Iaas上为每个用户构建容器集群,腾讯云提供的微服务架构和持续集成与交付的应用场景基本满足了我们的述求。
•    腾讯云的容器服务是基于Kubernetes实现的,支持完全的kubernetes能力。
•    腾讯云在Kubernetes上实现了他们的存储、负载均衡等产品的插件、复用了腾讯云本身平台的监控、日志等能力。减少了我们接入和开发的成本。

服务在腾讯云的应用
我们将我们的应用重构成微服务的架构,每个微服务部署成腾讯云容器服务上的一个服务,前端接入通过一个负载均衡。后端服务间可互相访问。
服务器安全方面,内部服务器通过VPC进行网络隔离,将网络划分为生产环境、测试环境,在生产环境中又划分backend子网和data子网,设定子网之间的访问规则。
为了禁止内部服务器的外网访问,不给内部服务器分配外网IP,仅通过跳板机访问。

性能对比
利用locust模拟线上请求的比例,利用2台16核的压测机在内网对10台16C32G的机器上的服务进行压测,达到1w/s QPS以上,并且服务的负载并没达到极限,这已经是之前PHP生产环境20+台16C32G服务器能达到的QPS。


线上调用追踪
通过追踪API调用链的流向与耗时,我们可以找出性能的瓶颈。我们通过zipkin实际优化了几种情况:
•    服务调用冗余
当拉取文章列表的时候,我们需要拉取文章对应的作者信息,开始的时候我们使用拉取单个作者信息的方式,后来性能调优阶段,我们将其改为批量拉取作者列表,减少RPC的冗余。
•    服务耗时长
对于有些本身就比较耗时并且对即时性不是那么苛刻的计算服务,我们为了保证服务的响应时间,会适量地加上缓存。

监控与报警
由从外部系统表征到内部日志,我们将监控分为API健康,程序错误报警,以及服务器/容器负载。
排查问题的流程一般有两种情况,一种是用户发现问题,申报问题,开发人员跟进问题;一种是我们的监控优先发现问题,开发人员在用户反馈前跟进并修复。在报警方面,我们通过为监控系统谨慎设置报警阈值,当触发报警时,开发人员会收到邮件。
这里我们在报警的定义上有过思考,即什么样的报警算是有意义的?我们遇到过每天10几条重复的报警,通常开发人员开始时会对报警非常重视,当重复的报警一再出现,渐渐失去了对报警的关注。所以我们有解除一些不必要的报警,并且对剩余一些报警进行调查,甚至有些警报是因为监控工具本身的不准确引起的。

API健康
我们设置默认的时间区间是5分钟
•    统计API五分钟内平均QPS
•    API 98%以内的延迟分布
•    QPS最高的前10的API
•    API的返回码的分布

程序错误报警
后端程序内接入Sentry日志报警系统,golang程序捕获panic日志以及error日志,并发送报警邮件。

服务器/容器负载
通过在服务器上运行telegraf daemon进程,收集服务器metrics并发送给influxdb,使用Grafana作为前端面板,对服务器负载以及容器的平均CPU、内存占用率进行监控。

结束语
本文介绍了华尔街见闻通过重构和服务容器的重新部署,实践微服务架构的情况。经过几个月的开发测试,我们不仅完成了线上服务从PHP到Golang的转型,更在服务的稳定性上经历了考验,支撑了几次重大新闻的高流量。
在开发流程上,搭建了完善的自动化工具,减少了人工操作的重复性和误操作概率。
在运维方面,由于监控系统对系统完整的监控,与Kubernetes健全的上线、下线、回滚、拓容功能配合,能以极快的速度处理线上问题。

使用Ansible会提示UserWarning: Module import pkg_resources

采菊篱下 回复了问题 • 2 人关注 • 1 个回复 • 371 次浏览 • 2017-05-08 23:39 • 来自相关话题

HTTP长连接和短连接介绍

being 发表了文章 • 0 个评论 • 298 次浏览 • 2017-05-06 13:29 • 来自相关话题

1、HTTP协议与TCP/IP协议的关系​
HTTP的长连接和短连接本质上是TCP长连接和短连接。HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议。IP协议主要解决网络路由和寻址问题,TCP协议主要解决如何在IP层之上可靠的传递数据包,使在网络上的另一端收到发端发出的所有包,并且顺序与发出顺序一致。TCP有可靠,面向连接的特点。
 
2、如何理解HTTP协议是无状态的
HTTP协议是无状态的,指的是协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。也就是说,打开一个服务器上的网页和你之前打开这个服务器上的网页之间没有任何联系。HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接)。
 
3、什么是长连接、短连接?
在HTTP/1.0中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。如果客户端浏览器访问的某个HTML或其他类型的 Web页中包含有其他的Web资源,如JavaScript文件、图像文件、CSS文件等;当浏览器每遇到这样一个Web资源,就会建立一个HTTP会话。
 
但从 HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头有加入这行代码:Connection:keep-alive在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的 TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接要客户端和服务端都支持长连接。
 
HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。
 
3.1 TCP连接
当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接 时它们可以释放这个连接,连接的建立是需要三次握手的,而释放则需要4次握手,所以说每个连接的建立都是需要资源消耗和时间消耗的

经典的三次握手示意图:








经典的四次挥手关闭图:
 








 
3.2 TCP短连接
我们模拟一下TCP短连接的情况,client向server发起连接请求,server接到请求,然后双方建立连接。client向server 发送消息,server回应client,然后一次读写就完成了,这时候双方任何一个都可以发起close操作,不过一般都是client先发起 close操作。为什么呢,一般的server不会回复完client后立即关闭连接的,当然不排除有特殊的情况。从上面的描述看,短连接一般只会在 client/server间传递一次读写操作

短连接的优点是:管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段
 
3.3 TCP长连接
接下来我们再模拟一下长连接的情况,client向server发起连接,server接受client连接,双方建立连接。Client与server完成一次读写之后,它们之间的连接并不会主动关闭,后续的读写操作会继续使用这个连接。

首先说一下TCP/IP详解上讲到的TCP保活功能,保活功能主要为服务器应用提供,服务器应用希望知道客户主机是否崩溃,从而可以代表客户使用资源。如果客户已经消失,使得服务器上保留一个半开放的连接,而服务器又在等待来自客户端的数据,则服务器将应远等待客户端的数据,保活功能就是试图在服务 器端检测到这种半开放的连接。

如果一个给定的连接在两小时内没有任何的动作,则服务器就向客户发一个探测报文段,客户主机必须处于以下4个状态之一:
客户主机依然正常运行,并从服务器可达。客户的TCP响应正常,而服务器也知道对方是正常的,服务器在两小时后将保活定时器复位。客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的TCP都没有响应。服务端将不能收到对探测的响应,并在75秒后超时。服务器总共发送10个这样的探测 ,每个间隔75秒。如果服务器没有收到一个响应,它就认为客户主机已经关闭并终止连接。客户主机崩溃并已经重新启动。服务器将收到一个对其保活探测的响应,这个响应是一个复位,使得服务器终止这个连接。客户机正常运行,但是服务器不可达,这种情况与2类似,TCP能发现的就是没有收到探查的响应。
 
长连接短连接操作过程:
短连接的操作步骤是:建立连接——数据传输——关闭连接...建立连接——数据传输——关闭连接

长连接的操作步骤是:建立连接——数据传输...(保持连接)...数据传输——关闭连接
 
4、 长连接和短连接的优点和缺点
由上可以看出,长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。对于频繁请求资源的客户来说,较适用长连接。不过这里存在一个问题,存活功能的探测周期太长,还有就是它只是探测TCP连接的存活,属于比较斯文的做法,遇到恶意的连接时,保活功能就不够使了。在长连接的应用场景下,client端一般不会主动关闭它们之间的连接,Client与server之间的连接如果一直不关闭的话,会存在一个问题,随着客户端连接越来越多,server早晚有扛不住的时候,这时候server端需要采取一些策略,如关闭一些长时间没有读写事件发生的连接,这样可 以避免一些恶意连接导致server端服务受损;如果条件再允许就可以以客户端机器为颗粒度,限制每个客户端的最大长连接数,这样可以完全避免某个蛋疼的客户端连累后端服务。

短连接对于服务器来说管理较为简单,存在的连接都是有用的连接,不需要额外的控制手段。但如果客户请求频繁,将在TCP的建立和关闭操作上浪费时间和带宽。

长连接和短连接的产生在于client和server采取的关闭策略,具体的应用场景采用具体的策略,没有十全十美的选择,只有合适的选择。
 
5、什么时候用长连接,短连接? 
长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况,。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。 
  
而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。 查看全部
1、HTTP协议与TCP/IP协议的关系​
HTTP的长连接和短连接本质上是TCP长连接和短连接。HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议。IP协议主要解决网络路由和寻址问题,TCP协议主要解决如何在IP层之上可靠的传递数据包,使在网络上的另一端收到发端发出的所有包,并且顺序与发出顺序一致。TCP有可靠,面向连接的特点。
 
2、如何理解HTTP协议是无状态的
HTTP协议是无状态的,指的是协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。也就是说,打开一个服务器上的网页和你之前打开这个服务器上的网页之间没有任何联系。HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接)。
 
3、什么是长连接、短连接?
HTTP/1.0中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。如果客户端浏览器访问的某个HTML或其他类型的 Web页中包含有其他的Web资源,如JavaScript文件、图像文件、CSS文件等;当浏览器每遇到这样一个Web资源,就会建立一个HTTP会话。
 
但从 HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头有加入这行代码:
Connection:keep-alive
在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的 TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接要客户端和服务端都支持长连接。
 
HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。
 
3.1 TCP连接
当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接 时它们可以释放这个连接,连接的建立是需要三次握手的,而释放则需要4次握手,所以说每个连接的建立都是需要资源消耗和时间消耗的

经典的三次握手示意图:
tcp.png

san.png

经典的四次挥手关闭图:
 
huishou.png

si.png

 
3.2 TCP短连接
我们模拟一下TCP短连接的情况,client向server发起连接请求,server接到请求,然后双方建立连接。client向server 发送消息,server回应client,然后一次读写就完成了,这时候双方任何一个都可以发起close操作,不过一般都是client先发起 close操作。为什么呢,一般的server不会回复完client后立即关闭连接的,当然不排除有特殊的情况。从上面的描述看,短连接一般只会在 client/server间传递一次读写操作

短连接的优点是:管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段
 
3.3 TCP长连接
接下来我们再模拟一下长连接的情况,client向server发起连接,server接受client连接,双方建立连接。Client与server完成一次读写之后,它们之间的连接并不会主动关闭,后续的读写操作会继续使用这个连接。

首先说一下TCP/IP详解上讲到的TCP保活功能,保活功能主要为服务器应用提供,服务器应用希望知道客户主机是否崩溃,从而可以代表客户使用资源。如果客户已经消失,使得服务器上保留一个半开放的连接,而服务器又在等待来自客户端的数据,则服务器将应远等待客户端的数据,保活功能就是试图在服务 器端检测到这种半开放的连接。

如果一个给定的连接在两小时内没有任何的动作,则服务器就向客户发一个探测报文段,客户主机必须处于以下4个状态之一:
  1. 客户主机依然正常运行,并从服务器可达。客户的TCP响应正常,而服务器也知道对方是正常的,服务器在两小时后将保活定时器复位。
  2. 客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的TCP都没有响应。服务端将不能收到对探测的响应,并在75秒后超时。服务器总共发送10个这样的探测 ,每个间隔75秒。如果服务器没有收到一个响应,它就认为客户主机已经关闭并终止连接。
  3. 客户主机崩溃并已经重新启动。服务器将收到一个对其保活探测的响应,这个响应是一个复位,使得服务器终止这个连接。
  4. 客户机正常运行,但是服务器不可达,这种情况与2类似,TCP能发现的就是没有收到探查的响应。

 
长连接短连接操作过程:
短连接的操作步骤是:建立连接——数据传输——关闭连接...建立连接——数据传输——关闭连接

长连接的操作步骤是:建立连接——数据传输...(保持连接)...数据传输——关闭连接
 
4、 长连接和短连接的优点和缺点
由上可以看出,长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。对于频繁请求资源的客户来说,较适用长连接。不过这里存在一个问题,存活功能的探测周期太长,还有就是它只是探测TCP连接的存活,属于比较斯文的做法,遇到恶意的连接时,保活功能就不够使了。在长连接的应用场景下,client端一般不会主动关闭它们之间的连接,Client与server之间的连接如果一直不关闭的话,会存在一个问题,随着客户端连接越来越多,server早晚有扛不住的时候,这时候server端需要采取一些策略,如关闭一些长时间没有读写事件发生的连接,这样可 以避免一些恶意连接导致server端服务受损;如果条件再允许就可以以客户端机器为颗粒度,限制每个客户端的最大长连接数,这样可以完全避免某个蛋疼的客户端连累后端服务。

短连接对于服务器来说管理较为简单,存在的连接都是有用的连接,不需要额外的控制手段。但如果客户请求频繁,将在TCP的建立和关闭操作上浪费时间和带宽。

长连接和短连接的产生在于client和server采取的关闭策略,具体的应用场景采用具体的策略,没有十全十美的选择,只有合适的选择。
 
5、什么时候用长连接,短连接? 
长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况,。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。 
  
而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。