月度归档:2015年03月

通过Spring获取properties文件属性值

Spring提供了注解@Value,用于在程序中获取properties配置文件属性值。例如:

1. applicationContext.xml中指定配置文件。

<context:property-placeholder location="classpath:xxx.properties" 
    ignore-unresolvable="true" />

当有多个配置文件时,上述配置可以配置多条。

<context:property-placeholder location="classpath:xxx.properties" 
    ignore-unresolvable="true" />
<context:property-placeholder location="classpath:yyy.properties" 
    ignore-unresolvable="true" />

2. Spring bean中使用@Value注解获取指定参数。

// xxx.properties配置项:
// server.ip=192.168.1.1
// server.port=8080

@Value("${server.ip}")
private String ip;

@Value("${server.port}")
private int port;

使用@Value注解的前提是当前对象的生命周期由Spring管理,是Spring bean,无论通过XML配置文件还是@Component、@Service等注解声明。假如一个对象的生命周期是我们程序自己管理的,比如常规用法下的new Object(),特别是做一些框架开发,经常用到Class.forName().newInstance()来实例化对象,那么想要反射为新创建对象的成员变量赋值时,如何借助Spring来获取已经解析好的properties属性值是个值得一试的探索。上述场景可以简化为:

如何在一个拥有Spring上下文的平台上,对不受Spring管理的对象使用依赖注入,达到类似@Value注解实现的功能。

思路也很简单,既然Spring已经解析过properties文件,那么通过某种手段把这些值暴露出来就可以了,EmbeddedValueResolverAware接口很适合做这件事情。Aware接口是定义一些能在Spring bean中操作Spring上下文信息的一类接口,常见的有ApplicationContextAware,可以在Spring bean中拿到ApplicationContext;BeanFactoryAware,可以在Spring bean中拿到Spring BeanFactory。这里的EmbeddedValueResolverAware也是类似功能,它定义了一个void setEmbeddedValueResolver(StringValueResolver resolver)接口方法,在bean初始化后,Spring回调setEmbeddedValueResolver()方法,将StringValueResolver对象注入到bean中,从这个对象中就能获取properties文件中的属性名称和值。用法如下:

1. 声明一个实现EmbeddedValueResolverAware接口的实例,用@Component注解声明为Spring bean,重写setEmbeddedValueResolver()方法,将StringValueResolver实例的引用保存下来,并且对外提供getPropertiesValue()方法,用于获取properties值。

@Component
public class PropertiesUtils implements EmbeddedValueResolverAware {
    
    privat StringValueResolver stringValueResolver;

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        stringValueResolver = resolver;
    }

    public String getPropertiesValue(String name){
        return stringValueResolver.resolveStringValue(name);
    }
}

2. 通过${key}作为name格式调用getPropertiesValue()方法,获取properties值。

String name = "${server.ip}";
String value = propertiesUtils.getPropertiesValue(name);

StringValueResolve解析出来的值都是String类型的,非String类型需要在拿到参数String值后自行转换。

本文只对特定场景下使用EmbeddedValueResolverAware接口借助Spring上下文从properties文件中获取参数值做了一个简单介绍,此方法有效但不唯一,供参考。

--EOF--

『大型网站技术架构:核心原理与案例分析』(六)

『大型网站技术架构:核心原理与案例分析』读书笔记系列:
(一):架构演化、模式、要素
(二):高性能架构
(三):高可用架构
(四):可伸缩架构
(五):可扩展架构
(六):安全性架构


『大型网站技术架构』(六):安全性架构

一、网站应用攻击与防御

1. XSS攻击

跨站脚本攻击(Cross Site Script, XSS)指攻击者通过篡改网页,注入恶意HTML脚本,在用户浏览网页时,控制用户浏览器进行恶意操作的一种攻击方式。

  • 反射型: 攻击者诱使用户点击一个嵌入恶意脚本的链接,达到攻击目的。
  • 持久型:攻击者提交含有恶意脚本的请求,保存在被攻击的Web站点数据库中,用户浏览网页时,恶意脚本被包含在正常的页面中,达到攻击目的。

防御手段:

  • 消毒:特殊字符('<','>'等)转义。
  • HttpOnly: 不能避免XSS,但是能避免攻击者通过XSS获取Cookie,导致敏感信息泄露。

2. 注入攻击

两种形式:SQL注入攻击、OS注入攻击。本质是将数据当做程序执行。

攻击者如何获取数据库表结构信息?

  • 开源:表结构本身公开。
  • 错误回显:服务器500错误回显到浏览器。
  • 盲注:攻击者根据页面变化情况判断SQL语句的执行情况,据此猜测数据库表结构。

防御手段:

  • 消毒:过滤数据中可能注入的SQL。
  • 参数绑定:预编译(两大好处:1.提升性能,2.防止SQL注入)

3. CSRF攻击

跨站请求伪造(Cross Site Request Forgery, CSRF)指攻击者通过跨站请求,以合法用户的身份进行非法操作。核心是利用浏览器Cookie或服务器Session策略盗取用户身份。

防御手段:识别请求者身份

  • 表单Token: 每次页面请求,服务器写入一个随机数到Cookie,下次页面表单提交,表单域携带随机数,服务器端以此判断Cookie中随机数与表单域中值是否一致。这个方法有效的前提是Cookie不泄露,否则不生效。CSRF配合XSS攻击盗取Cookie会带来严重后果。
  • 验证码:用户体验不好。
  • Referer cheker:判断Referer域中请求来源是否合法。

4. 其他攻击和漏洞

  • Error Code: 服务器端500错误异常信息直接显示在浏览器。
  • HTML注释
  • 文件上传:上传不可靠文件类型。
  • 路径遍历:URL路径部分填入相对路径,暴露服务器文件系统。

二、信息加密技术及密钥安全管理

1. 加密技术

  • 单项散列加密
  • 对称加密
  • 非对称加密

单向散列加密

通过对不同输入长度信息进行散列计算,得到固定长度输出,不可逆。

常见算法:MD5、SHA

对称加密

加密和解密使用的密钥是同一个(或者可以互相推算)。算法简单,加解密效率高,系统开销小,适合大量数据加密,如何保存密钥是个难题。

常见算法:DES、RC

非对称加密

加密和解密使用的密钥不是同一个。安全性高。

常见算法:RSA

2. 密钥安全管理

  • 密钥和算法放在一个独立的服务器上,甚至做成一个专用硬件设施,对外提供加密和解密服务,应用系统通过调用这个服务实现加解密。
  • 加解密算法放在应用系统中,密钥放在独立服务器,并且密钥分片存储,分别由专人保管。

三、信息过滤和反垃圾

  • 文本匹配:Trie算法、多级Hash表
  • 分类算法:数据挖掘、贝叶斯分类算法
  • 黑名单:Hash表(精确)、布隆过滤器(不完全精确)

四、电子商务风险控制

1. 风险

  • 账户风险
  • 买家风险
  • 卖家风险
  • 交易风险

2. 风控

  • 规则引擎:业务规则和规则处理逻辑相分离。规则处理逻辑写好后,由运营人员负责通过页面编辑规则。
  • 统计模型:数据挖掘、机器学习

--EOF--

『大型网站技术架构:核心原理与案例分析』(五)

『大型网站技术架构:核心原理与案例分析』读书笔记系列:
(一):架构演化、模式、要素
(二):高性能架构
(三):高可用架构
(四):可伸缩架构
(五):可扩展架构
(六):安全性架构


『大型网站技术架构』(五):可扩展架构

扩展性和伸缩性:

  • 扩展性(Extensibility): 指对现有系统影响最小的情况下,系统功能可持续扩展或提升的能力。目标是当系统新增功能时,不需要对现有系统的结构和代码进行修改。
  • 伸缩性(Scalability):指系统能够通过增加/减少自身资源规模的方式增强/减少自己计算处理事务的能力。目标是利用集群的方式增加服务器数量,提高系统的整体事务吞吐能力,实现线性伸缩性。

一、构建可扩展的网站架构

终极目标:系统间低耦合。如何分解系统的各个模块、如何定义各个模块接口、如何复用组合不同的模块构造一个完整的系统。

核心思想:模块化,并在此基础上降低模块间耦合性,提高模块复用性。

二、利用分布式消息队列降低系统耦合性

分布式消息队列通过消息对象分解系统耦合性,不同子系统处理同一个消息。

事件驱动架构

定义:事件驱动架构(Event Driven Architecture)通过在低耦合的模块之间传输事件消息,以保持模块的松散耦合,并借助事件消息的通信完成模块间合作。

典型的EDA架构比如生产者消费者模式。利用分布式消息队列的发布-订阅模式工作。生产者只需生产消息到队列,消费者从队列获取消息进行处理。新增业务,只要对某类消息感兴趣,即可订阅该消息,对原有系统和业务没有任何影响。

三、利用分布式服务打造可复用的业务平台

分布式服务通过接口分解系统耦合性,不同子系统通过相同的接口描述进行服务调用。

巨无霸系统带来的问题:

  • 编译、部署困难
  • 代码分支管理困难:多个团队共同维护一份代码。
  • 数据库连接容易耗尽:数据库连接数与应用数量成正比。
  • 新增业务困难:老人不敢碰,新人不能接。

解决方法:拆分、模块独立部署

  • 纵向拆分:将大应用拆分为多个小应用。
  • 横向拆分:将复用业务拆分出来,独立部署为分布式服务,新增业务只需调用这些分布式服务,不需要依赖具体的模块代码。

Web Service与企业级分布式服务

Web Service: 服务提供者通过WSDL描述服务(接口),客户端通过WSDL生成客户端调用代码,通过SOAP协议与服务提供者通信,传输层协议可以是HTTP、SMTP、TCP等。

缺点:

  • 臃肿的注册与发现机制
  • 低效的XML序列化手段
  • 开销相对较高的HTTP远程通信
  • 复杂的部署与维护手段

大型网站分布式服务的需求

  • 服务注册与发现
  • 负载均衡:支持服务请求者使用可配置的负载均衡算法访问服务。
  • 失效转移
  • 高效的远程通信
  • 整合异构系统
  • 对应用最小侵入:适应服务架构的进化和反复(分布式或集中式部署)。
  • 版本管理:支持服务接口的多版本。
  • 实时监控

分布式服务框架设计

  • Thrift(远程服务调用框架):Facebook用它管理其分布式服务(注册、发现和调用),但是未开源基于Thrift的分布式服务框架。
  • Dubbo:阿里开源的分布式服务框架,较为成熟。

四、可扩展的数据结构

NoSQL: 宽列存储模型、ColumnFamily(列族)设计、面向列族的稀疏矩阵存储格式

五、利用开放平台建设网站生态圈

开放平台架构:

  • API接口:RESTful、Web Service、RPC等。
  • 协议转换:将API输入转成内部服务可识别的形式,将内部服务返回值封装成API格式。
  • 安全:身份识别、权限控制。
  • 审计:监控、计费。
  • 路由:将开放平台访问路由映射到具体的内部服务。
  • 流程:将一组离散的服务组织成一个上下文相关的新服务,隐藏服务细节,提供统一接口。

--EOF--

『大型网站技术架构:核心原理与案例分析』(四)

『大型网站技术架构:核心原理与案例分析』读书笔记系列:
(一):架构演化、模式、要素
(二):高性能架构
(三):高可用架构
(四):可伸缩架构
(五):可扩展架构
(六):安全性架构


『大型网站技术架构』(四):可伸缩架构

“大型“定义:

  • Facebook: 大量用户及大量访问,10亿用户。
  • 腾讯: 功能复杂,产品众多,1600+种产品。
  • Google:大量服务器,100w台服务器。

一、网站架构的伸缩性设计

  • 不同功能进行物理分离实现伸缩

    单一服务器处理所有服务 -> 数据库从应用服务器分离 -> 缓存从应用服务器分离 -> 静态资源从应用服务器分离

    横向分离(分层后分离)、纵向分离(业务分割后分离)

  • 单一功能通过集群规模实现伸缩

    当一头牛拉不动车的时候,不要去寻找一头更强壮的牛,而是用两头牛来拉车。

    集群伸缩性:应用服务器集群伸缩性、数据服务器集群伸缩性(缓存数据服务器集群和存储数据服务器集群)

二、应用服务器集群的伸缩性设计

负载均衡:实现网站伸缩性,改善网站可用性。

负载均衡类型

1. HTTP重定向负载均衡

通过一台HTTP重定向服务器,返回302实现负载均衡。实践中很少见。

优点:简单
缺点:性能差(2次请求)、伸缩性有限(重定向服务器容易成为瓶颈)、被搜素引擎判为SEO作弊(302请求),

2. DNS域名解析负载均衡

在DNS服务器中配置多个A纪录。大型网站用于进行第一级负载均衡。

优点:支持基于地理位置域名解析,加快用户访问速度。
缺点:DNS多级解析,生效和失效时间久。

3. 反向代理负载均衡

利用反向代理服务器(缓存资源、安全等)进行负载均衡。应用层负载均衡。

优点:反向代理功能和负载均衡功能集成,部署简单。
缺点:反向代理服务器容易成为瓶颈。

4. IP负载均衡

在网络层通过修改请求目标地址进行负载均衡。

  • 负载均衡服务器修改目的IP的同时修改源地址,将数据包源地址设为自身IP。(SNAT)
  • 负载均衡服务器同时作为Real Server的网关服务器。(LVS/NAT模式)

优点:相比应用层负载均衡(反向代理)有更好的性能。
缺点:进出流量走负载均衡服务器,依然存在瓶颈。

5. 数据链路层负载均衡

在通信协议的数据链路层修改mac地址进行负载均衡(LVS/DR)。数据三角传输模式,流量从用户->负载均衡服务器->Real Server->用户。

目前使用最广泛。

负载均衡算法

  • 轮询(Round Robin, RR)
  • 加权轮询(Weighted Round Robin, WRR)
  • 随机(Random)
  • 最少连接(Least Connections)
  • 源地址散列(Source Hashing)

三、分布式缓存集群的伸缩性设计

目标:必须让新上线/下线的缓存服务器对整个分布式缓存集群影响最小,也就是说经过调整使整个缓存服务器集群中已经缓存的数据尽可能还被访问到。

一致性Hash:解决集群扩减容时过多节点缓存失效问题。
使用虚拟节点的一致性Hash环:避免集群扩减容造成的节点负载不均问题,通过增加一层虚拟节点与物理节点的映射来使节点增删带来的影响平均到所有节点。

四、数据存储服务器集群的伸缩性设计

数据存储服务器必须保证数据可靠存储、可用性、正确性,伸缩性设计原则与缓存不同。

1. 关系数据库集群的伸缩性设计

  • 主从读写分离
  • 业务分隔、数据分库。跨库不能Join操作、避免事务
  • 数据分片:通过分布式关系数据库访问代理,比如Amoeba、Cobar(Ali)。伸缩性:一致性Hash + 数据迁移

2. NoSQL数据库的伸缩性设计

HBase伸缩性: 依赖可分裂的HRegion及可伸缩的分布式文件系统HDFS实现。

--EOF--

『大型网站技术架构:核心原理与案例分析』(三)

『大型网站技术架构:核心原理与案例分析』读书笔记系列:
(一):架构演化、模式、要素
(二):高性能架构
(三):高可用架构
(四):可伸缩架构
(五):可扩展架构
(六):安全性架构


『大型网站技术架构』(三):高可用架构

一、可用性度量与考核

度量

衡量方式:多少个9。

网站不可用时间(故障时间) = 故障修复时间点 - 故障发现(报告)时间点

网站年度可用性指标 = (1-网站不可用时间/年度总时间) * 100%

  • 2个9:基本可用,年度不可用时间小于88小时
  • 3个9:较高可用,年度不可用时间小于9小时
  • 4个9:具有自动恢复能力的高可用,年度不可用时间小于53分钟
  • 5个9:极高可用,年度不可用时间小于5分钟

考核

故障分:对网站故障进行分类加权计算故障责任。故障分 = 故障时间(分钟) * 故障权重。

  • 事故级故障(100): 严重故障,网站整体不可用
  • A类故障(20): 网站访问不顺畅或核心功能不可用
  • B类故障(5): 非核心功能不可用,或核心功能少数用户不可用
  • C类故障(1): 以上故障以外的其他故障

二、高可用网站架构

高可用架构设计不仅要考虑软硬件故障,还要考虑网站升级发布引起的不可用。

主要手段: 数据和服务的冗余备份和失效转移。

典型分层模型:

  • 应用层: 负责具体业务逻辑处理。思路:负载均衡设备
  • 服务层: 负责提供可复用的服务。思路:分布式服务调用框架,客户端软件负载均衡
  • 数据层: 负责数据的存储与访问。思路:数据冗余

三、高可用应用

主要特点:无状态

无状态应用是指应用服务器不保存业务的上下文信息,仅根据每次请求提交的数据进行相应业务逻辑处理,多个服务实例完全对等。

1. 通过负载均衡进行无状态服务的失效转移

  • 应用访问量小也使用负载均衡技术构建一个小型集群保证高可用
  • 平滑升级

2. 应用服务器集群的Session管理

  • Session复制:Session在集群中同步,大集群不适用。
  • Session绑定:Session Sticky,会话黏滞。Hash(Source IP)、Hash(Cookie),无法实现高可用。
  • 利用Cookie记录Session:服务器端不记录Session,每次从Cookie中解,服务器可线性伸缩。缺点:大小受限、增大传输数据量、用户关闭Cookie时不可用。
  • Session服务器:独立部署Session服务器集群,通过 分布式缓存+数据库 实现。可用性高、伸缩性好、性能不错。

四、高可用服务

主要特点: 无状态

  • 分级管理:核心业务隔离部署、用更好更稳定的硬件。
  • 超时设置
  • 异步调用
  • 服务降级:拒绝服务(拒绝低优先级任务、随机拒绝)、关闭功能。
  • 幂等性设计:允许重复调用。

五、高可用数据

主要手段:数据备份和失效转移机制

含义:

  • 数据持久性
  • 数据可访问性
  • 数据一致性:

    • 1) 数据强一致:最强,各副本数据在物理存储中一致;
    • 2) 数据用户一致: 较强,在物理存储中可能不一致,但是通过纠错和校验机制,可以返回一个一致且正确地的数据给用户;
    • 3) 数据最终一致,较弱,用户得到的数据可能不一致,但是最终会达到一致。

CAP理论: 数据一致性(Consistency)、数据可用性(Availibility)、分区容忍性(Partition Tolerance)。大型网站中,通常会选择强化分布式存储系统的可用性(A)和伸缩性(P),在某种程度上放弃一致性(C)。

缓存服务讨论,两种观点:

  • 缓存需要高可用:缓存承担了业务中绝大多数数据读取访问,缓存服务失效会影响整个网站可用性。
  • 缓存不需要高可用:缓存服务不是数据存储服务,缓存失效引起服务器负载太大的问题应用通过其他手段解决。比如扩大缓存集群规模,单台缓存服务器失效带来影响较小。

数据备份

  • 冷备份:定期将数据备份到某种存储介质(磁带、光盘……)并物理存档保管。简单、廉价、技术难度低,无法保证数据最终一致,可能丢数据,无法保证数据可用性。
  • 热备份:

    • 异步热备:Master-Slave架构。写Master,返回操作成功响应,再由Master同步到Slave,这个过程可能失败。例子:MySQL半同步复制、读写分离等。
    • 同步热备:存储服务器互相间对等。数据多副本写入同步完成。

失效转移

  • 失效确认:1. 心跳检查。2. 应用程序访问失败报告。
  • 访问转移:数据读写重新路由
  • 数据恢复:恢复副本数量

六、高可用网站软件质量保证

  • 网站发布:平滑升级,从LB下线->更新程序->挂回LB
  • 自动化测试
  • 预发布验证:预发布服务器与线上机器的唯一不同就是没有配置在负载均衡上,外部用户无法访问。避免验证过程污染生产环境数据。
  • 代码控制:1. 主干开发、分支发布。2. 分支开发、主干发布。
  • 自动化发布:周四发布,火车发布模型(基于规则驱动的流程,一级级评审)
  • 灰度发布:分批次升级,等一批稳定运行后再上下一批。

七、网站运行监控

准则:“不允许没有监控的系统上线”

监控数据采集

  • 用户行为日志收集:服务器端日志、客户端日志
  • 服务器性能监控
  • 运行数据报告:业务场景相关

监控管理

  • 系统报警
  • 失效转移
  • 自动优雅降级

--EOF--