2021年9月

linux系统下查看svn服务是否启动,重启及设置开机重启

Linux系统中svn服务是否启动,重启及设置开机启动

 

安装完svn服务器后虽然好用但是因为经常重启Linux服务器,每次重启完就要去手动启动svn服务器,很是麻烦,于是在网上找了一些方法后,自己把svn服务器设置成开机启动

步骤一:安装svn服务器:

1. 安装SVN服务器:

检查是否已安装

# rpm -qa subversion

安装SVN服务器

# yum install httpd httpd-devel subversion mod_dav_svn mod_auth_mysql

验证安装

# cd /etc/httpd/modules
# ls | grep svn
mod_authz_svn.so
mod_dav_svn.so

查看版本

# svnserve --version

 

 

 

2. 代码库创建:

安装完成后要建立SVN库

# mkdir -p /opt/svn/repositories
# svnadmin create /opt/svn/repositories

执行后,自动建立repositories库,查看/opt/svn/repositories文件夹包含了conf,db,format,hooks,locks,README.txt等文件,说明一个SVN库已经建立。

 

 

 

 

3. 配置版本库:

进入上面conf文件夹下,进行配置:

a. 用户密码passwd配置:

# vi + passwd  //+表示光标放在文件最低端

修改passwd为一下内容:

[users]
# harry = harryssecret
# sally = sallyssecret
zhoulf=123456

 

b. 权限控制authz配置:

# vi + authz

设置哪些用户可以访问哪些目录,向authz文件追加以下内容:

[/]
zhoulf=rw  //给该用户访问所有库的权限  或 [repositories:/project]  //repository库的根目录权限 zhoulf=rw

/ 表示根目录及以下,根目录是svnserve启动时指定的,我们指定的是/opt/svn;/ 就是指对全部版本库都具有权限

repositories:/ 表示对库repositories的根目录设置权限

PS:

* 权限配置文件中出现的用户名必须已在用户配置文件中定义。

* 对权限配置文件的修改立即生效,不必重启svn。

 

c. 服务svnserve.con配置:

# vi + svnserve.conf

添加一下内容:

[general]
#匿名访问的权限,可以是read,write,none,默认为read
anon-access=none
#使授权用户有写权限
auth-access=write
#密码数据库的路径
password-db=passwd
#访问控制文件
authz-db=authz
#认证命名空间,subversion会在认证提示里显示,并且作为凭证缓存的关键字
realm=/opt/svn/repositories

这里注意各标签不能错,也不能有重复,不然无法连接。

 

d. 配置防火墙端口(如果需要):

不一定每个人都需要设置,可以先测试后再看是否需要打开端口

# vi /etc/sysconfig/iptables

添加一下内容:

-A INPUT -m state --state NEW -m tcp -p tcp --dport 3690 -j ACCEPT

保存后重启防火墙

# service iptables restart

 

4. 查看:

a. 启动SVN

# svnserve -d -r /opt/svn/repositories(你的svn所在目录)

 

b. 查看SVN进程

# ps -ef|grep svn|grep -v grep
root 12538 1 0 14:40 ? 00:00:00 svnserve -d -r /opt/svn/repositories

 

c. 检测SVN端口

# netstat -ln |grep 3690
tcp 0 0 0.0.0.0:3690 0.0.0.0:* LISTEN

 

 

5. 停止重启SVN:

# killall svnserve //停止
# svnserve -d -r /opt/svn/repositories // 启动

 

6. 测试连接:

(1)  在本地电脑上安装TortoiseSVN客户端:

        成功安装TortoiseSVN后在电脑桌面右键有TortoiseSVN提示;选择Repo-browser;会出现一个地址栏;

(2)在地址栏输入:svn://+服务器IP地址;如果安装没问题的话就会进入服务器的资源库

 

二、Linux服务器端设置svn开机启动

(1)在Linux服务器跟目录((/root路径下))创建一个脚本文件

     #  touch svn.sh

(2) 进入脚本文件

      # vim svn.sh

(3)添加一下内容

    #!/bin/bash
    /usr/bin/svnserve -d -r  /opt/svn/repositories

    解释一下:

               这里的svnserve路径保险起见,最好写绝对路径,因为启动的时候,环境变量也许没加载。
绝对路径怎么查?

      # which svnserve

(4)改该脚本的执行权限

    # chmod 777 svn.sh

(5)加入自动运行

     # vi /etc/rc.d/rc.local
在末尾添加脚本的路径:
       /root/svn.sh

(6)重启Linux服务器,重启后查看svn服务器是否已经开启

        #  ps -ef|grep svnserve

     如果显示以下信息表示svn已经开启了:

       tcp        0      0 0.0.0.0:3690            0.0.0.0:*               LISTEN


起源于20世纪70年代的电子商务,如今在全世界的发展可以说如火如荼,不断推陈出新;当下国内家居、零售、餐饮等传统行业也相继搭建自己的电商平台,凭借着多年积累的扎实的资金与地面部队、线下运营推广的实力,结合O2O模式,逐步在电商领域发力!

随着越来越多的实力派企业向电商领域进军,技术上如何快速搭建符合行业特点,有利于企业快速试水,同时便于后续可持续发展的电商平台,成为了关键的技术支撑需求。

如何在两个月时间内,迅速搭建类似京东、亚马逊、淘宝、卓越、当当的电商平台?需要从繁杂的电商业务系统中找到主流,需要借助开放的力量快速丰富和完善功能;而且,我们不能陷入为每家企业单独打造独立平台的泥潭,这就需要多租户与定制化。

要实现B2C电商平台必须具备的所有功能,包括卖场、商品、用户、社区、基础设施、促销价格、交易、订单、支付、虚拟资产、供应链、仓储、配送、财务、客服售后以及移动App等系统,还要满足一定的性能要求,使系统具备一定量级的用户服务能力,防攻击能力和内容分发效率,同时还要具备一定的可扩展性,为将来的升级扩容做准备。

从寻找产品、各种信息比较、订购、付款、送货到消费者服务和支持,构成电子商务的基本流程,我们需要根据必须的信息流、资金流和物流,对必须实现的模块进行筛选,以满足基本可用的电商平台需求。以卖场、移动、商品和用户系统为例,电商平台基本的业务架构见图1;抓主“流”,无招胜有招,不受常规完整性限制,就大胆迈出了快速搭建电商云平台的第一步。

图1 电商平台业务架构

即便如此,要做到这些基本的功能模块,不仅需要对电商业务非常熟悉,包括订单管道、拆分、暂停、转移、锁定、下传等正向流程,订单取消、重拆分、病单拉回、退款等逆向流程,以及开票业务、供应链业务、销售、支付处理、出入库等流程,还需要在技术上设计出一套综合考虑各种因素的,非常合理的技术架构,使得整个电商平台具备良好的技术指标,满足高性能、高可用、高并发、低成本的要求,还具备良好的可扩展性,这一点很重要,否则就是不计后果的野蛮开发。

首先,综合业务与技术方面的考虑,这个平台必须是开放的。

业务上,开放,可以借力ISV和有开发能力的租户。每个企业都有自己的ERP系统,要实现最后一公里的无缝对接,完全依靠平台的技术力量是不够的。这个时候如果把平台的业务能力开放出来,提供足够细粒度的API,ISV或有开发能力的租户就可以自行实现业务对接,并持续更新。随着业务的复杂,越来越多的需求会使平台开发者难以应对,而ISV和租户本身对自己的需求的理解是最贴切的,可以利用他们的力量,同时并行开发多个服务,只有这样才能快速丰富电商平台的服务,并确保这些服务的实用性。

技术上,完全依靠平台开发者的力量,初期维护几十上百个接口还可以,随着服务的增加,就只有依赖一套自动化的工具和平台,实现服务的轻量化。

众多服务的稳定性问题必然在服务轻量化以后对整个平台的稳定性问题带来明显的影响,这就需要从服务入手解决平台的稳定性问题。包括将Http服务异步化,使用事件驱动减少线程等待,通过虚拟隔离线程池将过度占用资源的业务排队,从而限定不同的业务所占用的资源等。

与此同时,还需要解决质量保障的问题。众多的ISV开发能力参差不齐,项目管理能力和开发风格也不尽相同,我们不仅需要制定一批规范,约定服务展现方式,包括窗口大小、ICON大小,颜色风格等;还需要制定完善的评审与上线流程,对于不同的服务,要求提交不同级别的测试报告。我们鼓励所有ISV服务都布署到云鼎或云擎平台,以便更好的管理并保障服务的稳定性和可用性。

以上这些都是根据用户需求和技术的需要,顺理成章。在解决了API的开放可用,以及基于开放API开发的服务的正确性和稳定性之后,我们需要一个服务市场供用户挑选和定制。随着服务的日益增多,我们的平台用户可能不知道自己已经购买的服务放到哪里去了,对于同一类服务,比如卖场、购物车、商品管理或交易管理,有多家ISV开发的多个服务,用户不知道该选用哪一个。这个时候就需要把这些服务在用户的桌面上聚合起来,便于用户查找和使用服务,引导用户使用更优秀的服务。尤其对于租户,可以提供Mobile Phone、Pad、WebBrowser、PC,包括Windows、Linux、MacOS、Android、iOS全平台跨OS的开放系统(架构见图2)。

图2 开放系统架构图

对于商家,可以通过Web、PC和移动端访问开放系统和其中由ISV开发的商品、交易、数据分析类应用;对于ISV可以通过Web访问管理站点;对于开放系统运营商则可以通过Web访问运营后台,进行ISV注册用户的维护、服务的审核等。

在Web、PC与移动端,开放系统通过一个壳将ISV开发的各类插件性质的服务聚合到一起实行统一管理和消息传递;这个壳和各个服务将调用服务器API,通过官方SDK、第三方SDK或直接调用开放系统API、第三方API,并在规范的开发框架下完成服务功能的实现。

所有API依赖于平台运营商和第三方提供的数据,建立在云平台基础之上。

接着,多租户模型的设计是必须面临的技术问题。不是说如何实现多租户,多租户模型已经是非常成熟的技术,已经有类似Salesforce这类的成熟应用将其实践到极致;这里面临的是如何在短时间内,快速搭建的电商平台中设计多租户模型,兼顾系统功能与开发效率,同时具备良好的系统可扩展性。

通常,多租户模型,一个实例服务一个租户(企业用户),通过创建不同的实例来实现服务的虚拟和自动扩展。与虚拟化技术最大的不同在于,虚拟化主要是指虚拟主机、内存等资源。

按照多租户模型,如图3所示,我们应该在AppLayer动态创建多个实例,分别服务于不同的租户;如果是单实例同时服务于多个企业用户,可以称之为多用户模式,在这种模式下,用户登录时通常需要选择企业名称或ID;在DataLayer通常采用共享数据库实例、共享表的方式存储多租户的数据。

图3 多租户网络架构

应用层如图4所示,通常在一个应用集群运行着多个应用实例,应用的实例将根据租户注册情况动态创建,根据用户使用情况动态调整和管理资源使用。

图4 多租户应用层架构

多租户模型所创建的多个实例是需要自动部署的,这就对系统的自服务能力提出了要求,在短期内有两种方案可以考虑。

一种是依赖云鼎、云擎平台,先实现多用户的方案,利用云鼎、云擎平台自动生成数据库实例。在企业用户少的情况下,是有利于快速搭建电商平台的。结合开放的需求,需要实现并开放基础的API、定制功能的API以及由定制功能生成的API(可分步骤实施)。

一种是暂时多租户共用实例。

如图5到图8所示,数据层通常有A、B、C、D四种架构,实现难度逐步增加,对开发团队的技术要求越来越高,租户定制功能的灵活度也由低到高。

图5 多租户数据层架构A

在私有库模式下,为每个租户单独创建一个数据库实例(或在一个数据库实例中创建多个数据库,这里将这种折中的模式归入此类),每个实例中运行着一套完整的业务表,在数据库内部,跟单租户系统没有任何区别。

图6 多租户数据层架构B

在私有表的模式下,每个租户将共享一个数据库实例,但在数据库实例内部,为每个租户创建一套完整的业务数据表。

图7 多租户数据层架构C

在扩展表模式下,基本表将负责每个租户独立数据的独享存储,扩展表将使用租户ID共享存储所有租户的定制数据,扩展表的字段类型通常是固定的。这种模式通常也采用私有元数据表、共享扩展表的方式来存放数据。

图8 多租户数据层架构D

在共享表(通用表或公有表)模式下,大量的表中存放着多个租户的数据,通过租户ID来区分和隔离,对于定制化的信息通常采用统一类型(如varchar)的稀疏列;由于存放了所有租户的数据,数据表和数据库的数据量都会很大,通常需要使用散列分区技术的大数据库系统。

从实现角度,实现最快的模式是应用层多用户+数据层A架构,次快的模式是应用层多租户+数据层A架构,效果最理想的是应用层多租户+数据层D架构。

数据库表的设计时,租户ID的设定,要有全局唯一的ID,每个租户的数据ID(如订单ID)要能够独立从1开始展现。

如果为了避免联合主键(联合查询,SQL语句会非常麻烦),可以考虑“7位租户ID+11位数据ID”(数字或字符),展现时取出后面11位的展现,同时存放租户ID方便应用使用。

如果更多的照顾到使用方便,可以使用租户ID与数据ID分开设计,以SKU-Price为例,如图9所示。

图9 租户ID的设计实例

定制可以先支持Logo、首页商品推荐区名称的设置、推荐商品的设置等,后期逐步结合模板实现复杂的UI(颜色、字体、布局等)、表格、业务流程和权限定制。

不同租户的定制功能涉及到开发量,不可能做到极致,解决的办法,一方面是依赖租户自身的开发力量,一方面是依赖ISV的力量,结合开放的需求,需要开放元数据表、数据表、透视表组合逻辑等(可分步骤实施)。

解决了基础数据问题,在UI和流程定制方面,需要制定一套完善的依赖模板的定制方案,如图10所示,是以Android系统为例的定制流程。

图10 模板定制流程

不妨自定义一套URI格式协议,包括协议头、host和activity名称和参数等信息,比如:“ecc://com.jd.eCloud/index=activityName?p1=v1&p2=v2”,在URIRequest中,与ISV约定根据协议写死地址,客户端只保留一套模板html页,从而实现不同的租户看到不同的展现。

另外,在开发组织与项目团队的管理方式上也需要辅助使用一定的方法和技巧。传统的走正步形式的瀑布开发模型一定不适合快速搭建的需要。

看板方式,把工作细分成任务,写在卡纸上,贴在墙上,把栏命名好,来显示任务在工作流程中的状况。

XP敏捷开发的Scrum模型兼具了多重优点,是比较常用的方法。

把来自各个职能部门的产品、开发和测试人员聚到一起,分成不同的开发小组,把工作细分成细小、实在的交付成果,安排人员负责需求清单以及跟据重要性排优先级别,由团队估算每个项目相对工量。

把整个开发时间分成固定时长的短迭代(通常一至四周),在每个迭代后演示新增可发布功能。

每个迭代中,ScrumMaster负责召开PlanMeeting,按照PO提出的优先级制定Sprint目标,创建SprintBacklog,以UserStory的方式分解成MVP功能点,估算工作量,承诺,生成故事卡、任务卡并上墙,开始维护BurndownChart,并定期召开SOS。

每个迭代发布后,经过评审,优化发布以及跟产品一起更新优先级别。

每个迭代发布后,进行回顾,优化过程。选用vagrant开发环境,可选ci/svn版本控制,通过cctray持续集成,通过代码赌场等活动提高代码质量。

如此快速搭建的电商平台,这里就关键几个架构问题和项目问题以及业务问题进行了讨论,具体在实施中如何在基础设施到网络架构方面做到高性能、高并发、高可用、高扩展、低成本,可以在单独的主题中进一步详细讨论。

http://www.csdn.net/article/a/2014-01-02/15817757


互联网架构“高并发”

 

一、什么是高并发

高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求


高并发相关常用的一些指标有响应时间(Response Time),吞吐量(Throughput),每秒查询率QPSQuery Per Second),并发用户数等。


响应时间:系统对请求做出响应的时间。例如系统处理一个HTTP请求需要200ms,这个200ms就是系统的响应时间。

吞吐量:单位时间内处理的请求数量。

QPS:每秒响应请求数。在互联网领域,这个指标和吞吐量区分的没有这么明显。

并发用户数:同时承载正常使用系统功能的用户数量。例如一个即时通讯系统,同时在线量一定程度上代表了系统的并发用户数。

 

二、如何提升系统的并发能力

互联网分布式架构设计,提高系统并发能力的方式,方法论上主要有两种:垂直扩展(Scale Up)与水平扩展(Scale Out

垂直扩展:提升单机处理能力。垂直扩展的方式又有两种:

1)增强单机硬件性能,例如:增加CPU核数如32核,升级更好的网卡如万兆,升级更好的硬盘如SSD,扩充硬盘容量如2T,扩充系统内存如128G

2)提升单机架构性能,例如:使用Cache来减少IO次数,使用异步来增加单服务吞吐量,使用无锁数据结构来减少响应时间;


在互联网业务发展非常迅猛的早期,如果预算不是问题,强烈建议使用“增强单机硬件性能”的方式提升系统并发能力,因为这个阶段,公司的战略往往是发展业务抢时间,而“增强单机硬件性能”往往是最快的方法。

 

不管是提升单机硬件性能,还是提升单机架构性能,都有一个致命的不足:单机性能总是有极限的。所以互联网分布式架构设计高并发终极解决方案还是水平扩展


水平扩展:只要增加服务器数量,就能线性扩充系统性能。水平扩展对系统架构设计是有要求的,如何在架构各层进行可水平扩展的设计,以及互联网公司架构各层常见的水平扩展实践,是本文重点讨论的内容。

 

三、常见的互联网分层架构


常见互联网分布式架构如上,分为:

1客户端层:典型调用方是浏览器browser或者手机应用APP

2反向代理层:系统入口,反向代理

3站点应用层:实现核心应用逻辑,返回html或者json

4服务层:如果实现了服务化,就有这一层

5数据-缓存层:缓存加速访问存储

6数据-数据库层:数据库固化数据存储

整个系统各层次的水平扩展,又分别是如何实施的呢?

 

四、分层水平扩展架构实践

反向代理层的水平扩展


反向代理层的水平扩展,是通过“DNS轮询”实现的:dns-server对于一个域名配置了多个解析ip,每次DNS解析请求来访问dns-server,会轮询返回这些ip

nginx成为瓶颈的时候,只要增加服务器数量,新增nginx服务的部署,增加一个外网ip,就能扩展反向代理层的性能,做到理论上的无限高并发。

 

站点层的水平扩展


站点层的水平扩展,是通过“nginx”实现的。通过修改nginx.conf,可以设置多个web后端。

web后端成为瓶颈的时候,只要增加服务器数量,新增web服务的部署,在nginx配置中配置上新的web后端,就能扩展站点层的性能,做到理论上的无限高并发。

 

服务层的水平扩展


服务层的水平扩展,是通过“服务连接池”实现的。

站点层通过RPC-client调用下游的服务层RPC-server时,RPC-client中的连接池会建立与下游服务多个连接,当服务成为瓶颈的时候,只要增加服务器数量,新增服务部署,在RPC-client处建立新的下游服务连接,就能扩展服务层性能,做到理论上的无限高并发。如果需要优雅的进行服务层自动扩容,这里可能需要配置中心里服务自动发现功能的支持。

 

数据层的水平扩展

在数据量很大的情况下,数据层(缓存,数据库)涉及数据的水平扩展,将原本存储在一台服务器上的数据(缓存,数据库)水平拆分到不同服务器上去,以达到扩充系统性能的目的。

 

互联网数据层常见的水平拆分方式有这么几种,以数据库为例:

按照范围水平拆分


每一个数据服务,存储一定范围的数据,上图为例:

user0库,存储uid范围1-1kw

user1库,存储uid范围1kw-2kw

这个方案的好处是:

1)规则简单,service只需判断一下uid范围就能路由到对应的存储服务;

2)数据均衡性较好;

3)比较容易扩展,可以随时加一个uid[2kw,3kw]的数据服务;

不足是:

(1)      请求的负载不一定均衡,一般来说,新注册的用户会比老用户更活跃,大range的服务请求压力会更大;

 

按照哈希水平拆分


每一个数据库,存储某个keyhash后的部分数据,上图为例:

user0库,存储偶数uid数据

user1库,存储奇数uid数据

这个方案的好处是:

1)规则简单,service只需对uid进行hash能路由到对应的存储服务;

2)数据均衡性较好;

3)请求均匀性较好;

不足是:

1)不容易扩展,扩展一个数据服务,hash方法改变时候,可能需要进行数据迁移;

 

这里需要注意的是,通过水平拆分来扩充系统性能,与主从同步读写分离来扩充数据库性能的方式有本质的不同。

通过水平拆分扩展数据库性能:

1)每个服务器上存储的数据量是总量的1/n,所以单机的性能也会有提升;

2n个服务器上的数据没有交集,那个服务器上数据的并集是数据的全集;

3)数据水平拆分到了n个服务器上,理论上读性能扩充了n倍,写性能也扩充了n倍(其实远不止n倍,因为单机的数据量变为了原来的1/n);

通过主从同步读写分离扩展数据库性能:

1)每个服务器上存储的数据量是和总量相同;

2n个服务器上的数据都一样,都是全集;

3)理论上读性能扩充了n倍,写仍然是单点,写性能不变;

 

缓存层的水平拆分和数据库层的水平拆分类似,也是以范围拆分和哈希拆分的方式居多,就不再展开。

 

五、总结

高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求

提高系统并发能力的方式,方法论上主要有两种:垂直扩展(Scale Up)与水平扩展(Scale Out)。前者垂直扩展可以通过提升单机硬件性能,或者提升单机架构性能,来提高并发性,但单机性能总是有极限的,互联网分布式架构设计高并发终极解决方案还是后者:水平扩展

互联网分层架构中,各层次水平扩展的实践又有所不同:

1)反向代理层可以通过“DNS轮询”的方式来进行水平扩展;

2)站点层可以通过nginx来进行水平扩展;

3)服务层可以通过服务连接池来进行水平扩展;

4)数据库可以按照数据范围,或者数据哈希的方式来进行水平扩展;

各层实施水平扩展后,能够通过增加服务器数量的方式来提升系统的性能,做到理论上的性能无限。


设计自己的高并发架构


在互联网行业,未来的趋势就是高并发分布式系统。

作为一名互联网开发人员,一定要把握发展趋势,并沿着正确的路线提升自己。我也是刚刚开始了解什么是高并发、分布式的系统,怎样进行这种系统的架构设计。我觉得学习的思路应该是:根据了解到的内容,参考已经存在的方案,自己思考,并动手设计一套自己的系统架构,哪怕十分简陋,但一定要了解每一部分设计或者优化的目的、原则、思路、具体方法和使用到的技术,然后再一步步完善其中的每一部分,不断加入最新的方案和技术,并在实际开发中不断实践自己的方案,最终形成自己最优的架构设计。

下面是我参考了很多架构设计方案后总结出的系统优化策略。

搭建高并发系统,或针对系统进行高并发优化,需要明确系统高并发出现的时间规律,地域(空间)规律。得到用户流量、区域分布、请求特点、应用服务瓶颈点、服务器的性能指标等等,根据这些因素有针对性地对业务流程本身、系统架构进行优化。

优化的原则:应该有灵活的扩展性、尽量低的成本、高性能。

优化的思路(出发点):



    1. 负载均衡系统

    2. 反向代理系统

    3. Web服务器系统

    4. 缓存系统

    5. 分布式存储系统

    6. 数据库集群系统

    7. 异步计算策略

一、负载均衡系统

在架构中加入负载均衡系统, 负载均衡系统可以使用的位置: 可以使用在web应用服务之前,也可用在数据库集群前(如:在MySQL集群中,使用LVS将数据库请求分散到各个从服务器)。

实现方式包括:硬件负载均衡、软件负载均衡。

硬件负载均衡效率高,价格贵,如F5等;

软件负载均衡系统价格低或免费,效率较硬件低,但一般够用,如LVS,nginx也有负载均衡功能。

二、反向代理系统

在系统架构中加入反向代理。

作用一:将请求映射到对应服务的服务器。首先需要划分业务,并统一约定和规范各个业务对应服务的URI,然后通过反向代理服务器将请求映射到各服务所在的服务器。这样可以避免在业务集中的情况下出现的单一功能发生瓶颈导致其他功能受到影响。(系统设计时,各业务服务应该按功能或模块进行拆分,便于进行横向分布式扩展)

作用二:提高系统吞吐量。数据在网络中传输很耗时,反向代理服务器可以使应用服务器不必再直接和客户端进行连接,阻塞进程等待数据接收完成,而是在反向代理服务器将数据缓冲完成后一次性快速传输给应用服务器。

作用三:对静态资源不必通过应用服务器,直接找到并返回,减轻应用服务器压力。

目前普遍使用Nginx作为反向代理服务器,它还是高性能http服务器,同时可以进行负载均衡。


三、Web应用系统优化

1.前端展示层:



    • 页面静态化(HTML化);


动态页面静态化,可通过CMS系统对非动态信息页面进行静态化(静态化实际就是用程序将html页面的代码输出到一个html文件中,就成了静态页面);

静态化后的页面同样可以通过CDN加速,或存入缓存。

适用于更新不频繁的内容。



    • 图片服务器和分离(CDN加速);

2.服务端程序:




    • 优化业务流程

    • 更高效的算法

    • 优化各种影响程序性能的代码细节

四、缓存系统

使用缓存减少对数据库的直接操作,减轻查询时的I/O压力

按照存放位置不同,可分为客户端缓存、服务端缓存。

1.客户端缓存(主要是缓存页面):



    • 浏览器缓存

    • 网关、代理服务器缓存


2.服务端缓存:



    • 页面缓存(常通过发布系统生成静态页面,适用于信息发布类网站,或数据非频繁进行动态变化的部分)。


缓存实现手段:可对页面整体缓存,也可以缓存片段,如ESI cache。使用CDN也算是一种缓存方式。



    • 数据缓存。


缓存框架:ehcache

NoSQL:redis、memcache

使用缓存还应该使缓存命中率更高。

五、分布式存储系统

对于需要占用大量存储空间的文档、图片、视频资源,单台服务器无法全部存储,需要大量大存储空间的服务器来保存,因此,使用大规模分布式存储系统提供基础的存储服务。


六、数据库系统

数据库的高性能方案有:优化当前数据库,和建立集群。

当数据库开始出现性能下降的时候,最优先的方案是:优化当前数据库的性能,而非立刻建立集群。应该保持简单原则,毕竟会增加很大复杂度。


1.当前数据库优化策略:



    • 建立索引

    • 优化sql

    • 使用效率更高的操作方式。如大量数据批量插入。


2.建立集群:



    • 读写分离

    • 从库的负载均衡

    • 分片、分库、分表(sharding)


3.mysql集群搭建方案:



    • 使用官方推荐:Mysql Cluster方案

    • 使用mysql中间件atlas方案

    • 其他集群方案


七、异步计算方案

对于实时性要求不高,或者不重要但很耗时的操作,采取异步执行方案。即先行返回结果,再继续执行。如将用户上传的文件进行分发到多台机器、图片处理、视频转码等操作。


高可用、高性能? 接口设计的 16 个原则

 

发起这个 Chat 只是一时兴起,想了一些点就写出来了,但自己一读,感觉一点干货都没有,真是汗颜。但还是也希望此拙文能带来一些你的思考,欢迎交流。

接口设计需要考虑哪些方面

  1. 接口的命名。

  2. 请求参数。

  3. 支持的协议。

  4. TPS、并发数、响应时长。

  5. 数据存储。DB选型、缓存选型。

  6. 是否需要依赖于第三方。

  7. 接口是否拆分。

  8. 接口是否需要幂等。

  9. 防刷。

  10. 接口限流、降级。

  11. 负载均衡器支持。

  12. 如何部署。

  13. 是否需要服务治理。

  14. 是否存在单点。

  15. 接口是否资源包、预加载还是内置。

  16. 是否需要本地缓存。

  17. 是否需要分布式缓存、缓存穿透怎么办。

  18. 是否需要白名单。

当我们设计接口,我们或多或少都会有上面列举的一些考虑,我们只有想的更多才能让让我们的接口更加完善,我个人觉得100%完美的接口是不存在,只有适合才是最重要。

接口设计原则

原则一:必须符合Restful,统一返回格式,约定业务层错误编码,每个编码可以携带可选的错误信息。

原则二: 命名必须规范、优雅。

原则三:单一性。

单一性是指接口要做的事情应该是一个比较单一的事情,比如登陆接口,登陆完成应该只是返回登陆成功以后一些用户信息即可,但很多人为了减少接口交互,返回一大堆额外的数据。

比如有人设计一个用户列表接口,接口他返回每一条数据都是包含用户了一大堆跟另外无关的数据,结果一问,原来其他无关的数据是他下一步想要获取的,想达成数据的懒加载。

原则四:可扩展。

接口扩展性,是指设计接口的时候多想想多种情况,多考虑各个方面,其实我觉得单独将扩展性放在这里也是不妥的,感觉说的跟单一性有点相反的意思,其实这个不是这个意思。

这边的扩展性是指我们的接口充分考虑客户端,想想他们是如何调用的,他要怎样使用我的代码,他会如何扩展我的代码,不要把过多的工作写在你的接口里面,而应该把更多的主动权交给客户程序员。

如获取不同的列表数据接口,我们不可能将每个列表都写成一个接口。 还有一点,我这里特别想指出来的是很多开发人员为了省事(姑且只能这么理解),将接口设计当成只是 app 页面展示。

这些人将一个页面展示就用一个接口实现,而不考虑这些数据是不是属于不同的模块、是不是属于不同的展示范畴、结果下次视觉一改,整个接口又得重写,不能复用。

原则五:必须有文档。

良好的接口设计,离不开清晰的接口文档表述。文档表述一定要足够详细

原则六:产品心。

为什么我说要有产品心?因为我觉得很多人忽略了这一点。我来说一下假如开发一个app,如果一开始连个交互文档给你都没有的话,你怎么设计接口?

所以我觉得作为一个服务端后台开发人员应该要有产品心,特别是对于交互文档应该好好理解,因为这些都会对我们的接口设计有很大的影响。

我在设计接口的时候就很常发现很多交互文档根本就走不通,产品没有考虑到位,交互文档缺失,这时候作为一个开发要主动推动,完善。

原则七:第三方服务接口数据能缓存就缓存。

原则八:第三方服务需要做降级。

原则九:建议消除单点。

原则十:接口粒度要小。

原则十一:客户端能处理的逻辑就不要给服务端处理,减少服务端压力。

原则十二:资源预加载。

原则十三:不要过度设计。

原则十四:缓存尽量不要穿透。

原则十五:接口能缓存就缓存。

原则十六:思辨大于执行

如何保证接口的高可用、高性能

上面也列举很多需要考虑和设计的原则,其实还有很多方面,我这边也不是特别全面。

居于上面列举的这些考虑点,其实这边说服务是更恰当,能把上面说的点做好,其实接口也是比较可靠,如何设计以及保证接口的高可用和高性能。可以思考一下以下几个 point

高性能:如果我们发现这个接口tps和响应时间没有达到我们的要求怎么办。

  • A:数据存储方面:我们会想数据库有没有分库、分表、有没有做主从,有没有读写分离、字段是否有加索引、是否存在慢 sql,数据库引擎是否选用合适、是不是用了事务;

    其次我们会想到是不是引用了分布式缓存、缓存 key 大小是否合适,失效时间是否设置合理,会不会大量缓存穿透、有没有引入本地缓存。

  • B:业务方面:是否有大量的计算、能否异步处理。是否需要引入线程池或者 MQ 来异步处理任务。有没有必要将接口进行垂直拆分和水平拆分、将接口粒度变小。

  • C:其他方面:nginx 层面做缓存、加机器、用 ssd,资源放 cdn,多机房部署、资源文件预加载。

高可用:如何保证服务高可用,需要从几个维度来实现:

  • A:消除单点,基于高可用第二位。

  • B:能做集群的全部做集群。譬如 Redis 集群、mysql集群、MongoDB副本集。

  • C:能做读写分离的都做读写分离。

  • D:异地多机房部署,接入 GSLB

  • E:必须有限流、降级机制。

  • F:监控。高可用的保证,基于第一位。

下图是从一个基本的请求出发来梳理需要涉及到各个段,以及各个端能做的事情。谈谈接口服务,但不局限于接口本身。

0?wx_fmt=png

  1. 客户端:资源预加载、限制请求、数据上报。我这边就拿客户端来举个例子。接口服务所依赖的资源包或者一些公共配置预加载在本地,减少接口的交互,通过请求配置文件是否更新,code是否是304等来;

    接口做一些请求限制,比如抢红包、抢券等,单位时间内N次点击只请求一次等;接口失败数据上报来;这就是客户端可以做到的对接口有帮助的事情

  2. GSLB/HttpDNS:多机房部署、流量切换、域名劫持,一般技术和业务比较成熟的公司这一层。

  3. 资源文件放CDN。

  4. 负载均衡器:lVS+Nginx是互联网常用的做负载均衡,可以实现四层/七层负载均衡;这里除了可以分流、转发以外,我们用的更多的基于令牌桶限流、缓存。

  5. 本地缓存。本地缓存能减少我们访问DB或者分布式缓存,本地缓存推荐使用guava,guava里面有很多特性很好用,例如基于令牌桶的限流;当缓存失效时只穿透一个请求去访问后端。

  6. 线程池。

  7. 模块拆分。将一个项目按功能模块拆分,一个接口也可以按业务粒度进行拆分。

  8. 数据中心。提供数据支撑,譬如黑名单。

  9. 数据库。加索引、分库、分表、读写分离

  10. 分布式缓存。数据分片、拆分大key,并做集群,采用分布式锁

  11. MQ。做接口拆分利器,异步操作。

  12. 其他服务。限流、防刷以及降级(特别是第三方服务,保证第三方服务down掉不要影响我们自身的服务)。在这里也需要考虑做第三方数据的缓存或者持久化,譬如实名认证、身份证认证等。

  13. 监控。监控永远是必须的,能让你第一时间知道接口服务是否ok

个人小分享

1)接口Restful,统一返回格式,约定业务层错误编码,每个编码可以携带可选的错误信息

在前司,客户端和服务之间是有统一的数据返回格式,约定各层的编码,可以通过编码位数以及编码就可以看出是那一层出问题。

我觉得这对我们定位问题以及维护来说具有莫大的意义,并对异常也进行捕捉,封装成对应的 code,我之前阅读一些人的代码发现其项目根本没有做这一层,因为简单而不做我觉得有失所望。

2)采用 hybird 模式

采用 hybird 模式涉及到资源预加载的问题,在很多项目里面都大量使用,譬如前司的生活服务,就采用了 hybird 模式,先将资源文件(包含图片、前端页面)打包放到服务器并通过版本号进行管理,并通过一个总的配置文件来管理,如果是H5页面可以进行模板预先设计,down到本地。

配置文件格式:

 

  *文件1*        name:xxx        url:http:xxxx        md5:xxxx   *文件2*        name:zzz        url:http:zzzz        md5:zzz

客户端每次启动应用或者定时请求总的配置文件,通过http code是否是304判断是否需要下载这个总的配置文件,如果code是200,那么下载这个配置,比较那个文件发生变化,并将其下载。这样的好处:

  1. 减少接口的交互;

  2. 资源预加载,节省流量,打开页面更加流畅,对于服务端来说字需要返回数据json串就行,而不需要其他,减少服务端压力;

  3. 方便开发人员,资源管理更加简洁,比如做活动需要的h5页面,只需要前端上传对应的h5资源包到服务端,不需要通过后端开发人员就可以搞定。

虽然这个原理很简单,但是现在很多app还是没有做这个,都是通过填写一个url,加载网页的方式去打开,体验性太不友好。

3)客户端

客户端跟服务端就是接口请求的关系,很多时候需要要求客户端做一些数据缓存的工作以及一些检验工作。在前司已经好几次给客户端的同学坑过了,客户端同学接口乱调用,死循环调用。

一次是做一个关于事件提醒的功能,需要每天定时调用调用服务端一个接口,结果客户端的同学写了一个 bug 导致请求每隔一两秒就调用一次,导致服务器这边此接口 pv 翻了N倍,而且这个 bug 通过测试同学很难测试出来;

还有一次发现服务端一段时间以后 UV 不见涨,但是PV却涨的很猛,定位发现是客户端同学A图省事在一个方法里面调用了N个接口,也就是模板方法。

因为版本更新,同学B需要做一个新的功能,然后也调用了A同学的接口导致,从而导致PV上升,其实B同学完全不需要调用这么多接口。这些都是真实案例,所以这里需要有一个监控接口异常的机制。

4)思辨大于执行

写到这里觉得这个非常重要,思辨大于执行,意味着我们不是一股脑就去干,也不是不去干,我们做事情需要思考、辨别;从而让事情更高效、更好、更有力的执行。接口设计也一样,需要我们去思辨。

5)本地缓存、分布式缓存以及异步

缓存在前司主要分为客户端缓存、CDN缓存、本地缓存(guava)、Redis缓存。

在MZ早期是接口是采用 DB+本地缓存的方式提供数据,但这种模式DB压力大,接口吞吐量小,本地缓存多机难一致性、更新不及时问题。

为了解决这些问题,引入分布式缓存,并通过 Task 将业务数据刷到 Redis,接口只访问 redis,不会访问 DB,及时 DB 故障也不会影响功能。

不同的业务系统系统通过 MQ 来解耦,多机房不是通过 MQ 来实现数据的一直。

比如,评论,先通过写 Redis,写 MQ 来实现数据在多机房同步,再通过 task 将 Redis 中评论同步到 DB 中。

接口设计涉及方方面面,这边也只谈到一个大概,虽然有点泛泛而谈,希望此拙文对你有所启示。

6)数据库

数据库分库分表,一般都是通过 userId 或者 imei 或者 mac 地址来分表,单表数据量控制在500w以内,这需要我们提前估算好数据量,尽量避免数据的迁移。

在前司,数据库一般都是采用 mysql+MongoDB 两种,MySQL存储用户的用户数据,MongoDB 存储业务数据,就像阅读和生活服务里面的业务数据就存储在 MongoDB 里面。

在数据库这层,我们主要也是通过主从模式、读写分离、分库、分表来实现数据的可用性。

7)业务

业务尽可能拆分、独立部署、将项目按业务划分、按功能划分等。譬如生活服务,我们当时主要拆分成管理后台 admin、任务 task、活动、web、数据展示模块。

8)数据中心

每个大一点的公司都有数据部门,我们这边可以通过数据中心的数据分析来达到我们需要的数据。

比如黑名单,推广效果、活动数据。我们可以通过这些完善我们的接口功能。之前在前司做了个数据处理后异步加载到 Redis 来实现数据利用的项目。