微服务之分布式⽂件系统
背景
传统Web应⽤中所有的功能部署在⼀起,图⽚、⽂件也在⼀台服务器;应⽤微服务架构后,服务之间的图⽚共享通过FTP+Nginx静态资源的⽅式进⾏访问,⽂件共享通过nfs磁盘挂载的⽅式进⾏访问,⽆论是单体架构还是微服务架构下的应⽤都存在⼤量图⽚、⽂件读写操作,但是昂贵的磁盘空间、⾼性能服务器⽆疑增加了运营成本。
所以我们希望⽂件服务也能微服务、独⽴化,这样既能降低运营成本,⼜能对⽂件进⾏统⼀的管理和维护,所以搭建独⽴的⽂件服务是解决⽂件共享、释放业务系统压⼒的最优选择。于是便诞⽣了随⾏付分布式⽂件系统简称OSS(Object Storage Service),提供的海量、安全、低成本、⾼可靠的云存储服务。它具有与平台⽆关的RESTful API接⼝,能够提供数据可靠性和服务可⽤性。
⽂件服务的意义
随着互联⽹图⽚、视频时代的到来,对⽂件的处理成为各个业务系统⾯临的巨⼤挑战,没有⽂件服务器之前,系统之间处理图⽚的⽅式⼤相径庭:FTP、NFS、数据库存储等等,虽然都实现了对⽂件的存储、访问,但是系统之间很难达到⽂件共享,所以⽂件服务可以形成⼀个统⼀的访问标准,降低各个系统之间的互相依赖,提⾼开发效率、释放业务系统压⼒,所以⽂件服务的意义如下:
降低WEB服务器压⼒
分担业务服务器的I0、流程负载,将耗费资源的⽂件访问、读写操作分离到⽂件服务器,可以提⾼服务器的性能和稳定性,降低WEB服务器成本。
独⽴服务易扩展
⽂件服务像微服务架构独⽴化,可以有针对性的进⾏配置提⾼性能;独⽴域名让图⽚管理、CDN缓存⽂件更⽅便,随时扩展⽂件服务器数量,即不影响业务⼜能增加⽂件服务器并发访问。
统⼀访问格式
开发者⽆需关⼼存储路径、存储介质、⽂件备份等,丰富的API帮助系统快速存储、共享⽂件,提⾼项⽬开发速度。
安全认证
⽂件服务对资源访问可以增加认证、权限等安全措施,防⽌服务器资源被盗⽤,有效的隔离了数据访问。
⽂件服务基本概念
为便于更好的理解对象存储OSS,需要了解对象存储中的⼏个概念。
对象/⽂件(Object)
对象是OSS存储数据的基本单元,也被称为OSS的⽂件。对象由元信息(Object Meta),⽤户数据(Data)和⽂件名(Key)组成。对象由存储空间内部唯⼀的Key来标识。对象元信息是⼀个键值对,表⽰了对象的⼀些属性,⽐如最后修改时间、⼤⼩等信息,同时⽤户也可以在元信息中存储⼀些⾃定义的信息。对象的⽣命周期是从上传成功到被删除为⽌。在整个⽣命周期内,对象信息不可变更。重复上传同名的对象会覆盖之前的对象,因此,OSS 不⽀持修改⽂件的部分内容等操作。
存储空间(Bucket)
存储空间是⽤于存储对象(Object)的容器,所有的对象都必须⾪属于某个存储空间。可以设置和修改存储空间属性⽤来控制地域、访问权限、⽣命周期等,这些属性设置直接作⽤于该存储空间内所有对象,因此可以通过灵活创建不同的存储空间来完成不同的管理功能。
同⼀个存储空间的内部是扁平的,没有⽂件系统的⽬录等概念,所有的对象都直接⾪属于其对应的存储空间。 每个⽤户可以拥有多个存储空间。 存储空间的名称在 OSS 范围内必须是全局唯⼀的,⼀旦创建之后⽆法修改名称。 存储空间内部的对象数⽬没有限制。
访问密钥(AppKey & AppSecret)
AppKey代表应⽤⾝份,AppSecret即应⽤密钥,⽤于⽣成签名认证,请求⽂件服务时必须要传递appkey和签名⽣产的token,⽹关根据请求验证请求的合法性性和时效性。
⽂件服务的功能
应⽤场景 功能描述
上传⽂件 创建存储空间后,您可以上传任意⽂件到该存储空间
搜索⽂件 可以在存储空间中搜索⽂件或⽂件夹
查看或下载⽂件 通过⽂件 URL 查看或者下载⽂件
删除⽂件或⽂件夹 删除单个或者多个⽂件/⽂件夹,还可以删除分⽚上传产⽣的碎⽚,节省存储空间 访问权限 可以通过应⽤授权和桶授权的⽅式,授予存储空间和对象访问权限的访问策略
访问信息 ⾃动记录对OSS资源的详细访问信息
防盗链 防⽌OSS上的数据被其他⼈盗⽤,设置防盗链
监控服务 预警OSS服务使⽤情况的实时信息,如基本的系统运⾏状态和性能
API和SDK OSS 提供 RESTful API和各种语⾔的SDK开发包⽅便您快速进⾏⼆次开发 架构设计
OSS以分布式⽂件系统ceph作为底层存储,⽀持SDK或者浏览器以http的形式上传和下载⽂件,⽹关负责路由访问请求到⽂件服务集ossWork,ossWork⽣成⽂件唯⼀保存路径后存储⽂件到ceph,并返回加密后访问地址给⽤户。 架构图如下:
原理介绍:
1.OSS采⽤OpenResty作为⽹关处理请求转发和校验,OpenResty汇聚了nginx的核⼼功能模块,还⽀持lua脚本⽅便对nginx功能的扩展,⽽且nginx多路复⽤机制和⾮阻塞的IO⾮常适合耗时短、业务简单的校验操作:权限验证、防盗链、⿊⽩名单等,不仅如此nginx还能作为⽹关的缓存,这些特性极⼤提升了⽹关性能和并发访问。
2.ossWork作为⽂件服务,处理图⽚⽔印、缩放、url加密、解密等,还封装与底层存储的交互。
3.ossKeeper作为⽂件管理后台,负责权限接⼊注册、申请、监控报表展⽰。
4.ossMonitor⽇志收集、计算汇总、数据存储。
5.ossBackup负责⽂件异步备份。
oss⼦系统相关流程图如下:
核⼼实现
OSS主要为随⾏付各个业务系统提供⽂件共享和访问服务,并且可以按应⽤统计流量、命中率、空间等指标。下⾯将介绍OSS核⼼功能以及实现。主要包括:缓存、⽤户认证、权限管理、url加密解密、监控统计等。
缓存
提升性能的关键是缓存,OSS采⽤⼆级缓存:浏览器缓存、⽹关层缓存提升响应速度,具体如下:
第⼀次请求⽂件时,OSS返回⽂件给浏览器http的状态码是200分布式和微服务的关系
第⼆次请求时同⼀个⽂件时,服务器根据请求中HTTP协议中的max-age/Expires,判断⽂件未修改,返回状态码403,告诉浏览器可以继续使⽤本地缓存
第三次请求F5强制刷新,⽹关根据If-Modified-Since、Cache-Control:no-cache和Pragma:no-cache等
信息重新返回nginx中缓存⽂件第四次请求url时,requesturi不⼀样但⽂件是同⼀个,nginx根据requesturi判断⽹关中⽆此⽂件,请求底层存储返回⽂件。
⽤户认证
为避免⽂件、图⽚盗⽤,浪费服务器流量和IO等资源,OSS采⽤防盗链的⽅式认证请求。每个使⽤OSS服务的系统都需要进⾏注册、申请应⽤,成功后⾃动⽣成appkey、appsecret。appkey代表应⽤⾝份,appsecret即应⽤密钥,⽤于⽣成签名认证,请求⽂件服务时必须要传递appkey和签名⽣产的token,⽹关根据请求验证请求的合法性性和时效性。后台管理appkey的⽣成及防盗链的签名如下图:
⼿机终端认证
⼿机端认证同server端⼀样,但是由于账户信息的安全问题,appkey和appsecret只能保存在服务端,⼿机终端访问oss时⽆法⽣成签名,那么⼿机端如何访问oss服务?这⾥我们采⽤oauth认证的原理:
app⽤户登录终端系统,App发送请求OSS request请求
server收到请求后,向OSS申请资源的临时授权token
OSS接收授权请求后,⽣成临时访问token返回给server
server组装⽂件地址与临时的token,返回给app
权限管理
每个应⽤有了⾃⼰的appkey,⽂件访问时通过appkey验证⾝份,默认⽂件的归属只有上传者可以查看或修改,上传者可以授权给其他账户,通过在后台管理-权限配置功能授权授权的级别分为:修改、查看、删除,不同的级别对应不同的操作,后台管理系统会实时同步⽂件权限到⽂件系统。这样其他账户只需要传递⾃⾝的appkey就可以对此⽂件访问。具体流程及具体配置如下:
URL加解密、规范(实现参考)
底层存储中的⽂件名称必须全局唯⼀,oss采⽤⾃定义算法⽣成⽂件名称,命名规范=时间戳+分隔符+线程ID+分隔符+进程ID+分隔符+客户端IP,URL规范图解如下:
为了保证oss服务器的安全,防⽌程序⽂件和⽬录外泄,oss对url进⾏了私有协议的加密,按分隔符“_”对每⼀项进⾏base64编码,再按62位字典码加密⽣成加后的url,当然也有其他的算法实现,是要实现url加密即可。解密是对加密的逆向操作,解密后的url即为储存的访问url。服务端的规范样例及客户端的url规范样例:  oss统计监控
为保证⽂件服务的质量和可靠性,系统的监控和告警是必不可少的,各个阶段的运⾏信息,以⽇志的
形式写到⽂件中,再使⽤Flume⽇志收集组件采集各个⼦系统的⽇志,按⽇志类别直接发送到kafka的不同topic,ossMonitor读取kafka中消息,以时间为单位计算流量、命中率,以空间为单位统计使⽤率,根据上传⽇志是否有异常发送告警邮件,流程如下:
Flume是由cloudera软件公司产出的可分布式⽇志收集系统,由source,channel,sink三个组件组成:
Source:
从数据发⽣器接收数据,并将接收的数据以Flume的event格式传递给⼀个或者多个通道channal,Flume提供多种数据接收的⽅式,⽐如Avro,Thrift,txt等
Channel:
channal是⼀种短暂的存储容器,它将从source处接收到的event格式的数据缓存起来,直到它们被sinks消费掉,它在source和sink间起着⼀共桥梁的作⽤,channal是⼀个完整的事务,这⼀点保证了数据在收发的时候的⼀致性. 并且它可以和任意数量的source和sink链接. ⽀持的类型有: JDBC channel , File System channel , Memort channel等.
Sink:
sink将数据存储到集中存储器⽐如Hbase和kafka,它从channals消费数据(events)并将其传递给⽬标地.
Flume配置如下:
gateway.sources = fileEvent gateway.channels = kafkaChannel gateway.sinks = loggerSink
For each one of the sources, the type is defined
gateway.pe = TAILDIR gateway.sources.fileEvent.positionFile = / xxx.json
gateway.sources.fileEvent.filegroups = events gateway.sources.fileEvent.filegroups.events=/xxx.log
#gateway.pe = spooldir
The channel can be defined as follows.
gateway.sources.fileEvent.channels = kafkaChannel #gateway.sources.fileEvent.channels = kafkaChannel
#gateway.sources.fileEvent.spoolDir = /home/app/oss_events
Each sink's type must be defined
gateway.pe = org.apache.flume.sink.kafka.KafkaSink
#Specify the channel the sink should use gateway.sinks.loggerSink.channel = kafkaChannel
gateway.sinks.pic=oss-gateway-events gateway.sinks.loggerSink.kafka.batchSize=20 gateway.sinks.loggerSink.quiredAcks=1
Each channel's type is defined.
gateway.pe = memory
Other config values specific to each type of channel(sink or source)
can be defined as well
In this case, it specifies the capacity of the memory channel
gateway.channels.kafkaChannel.capacity = 30000 gateway.ansactionCapa
city = 100统计图如下:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。