Archive for May, 2016

作者:AngryFox 分类: Uncategorized May 29th, 2016 暂无评论

建推荐系统 涉及到实时计算、离线计算,以及各种数据采集、流转等
大数据有三个非常经典的应用:计算广告、搜索、推荐。推荐系统一般包括展现子系统、日志子系统和算法子系统三个部分,是数据要能够“存、通、用”

单元测试
持续集成(Gitlab-CI,phpunit,phpcs,phpmd,quickbuid)
监控和日志检索(Rsyslog, Elasticsearch,Kibana,Zabbix,Graphite,plog,kafka,hangout)
配置管理和异常反馈系统 AOE,SLA

性能优化思路
预估流量
性能评估
找出瓶颈
预案和容灾演练

一个理解误区:用防火墙和IDS/IPS能够缓解DDoS攻击。事实上,防火墙不是用来阻挡DDoS的,目前的DDoS攻击大部分基于合法数据包,防火墙难以有效监测;同时,防火墙是高强度的检查作为代价来进行防护的,DDoS攻击中的海量流量会造成防火墙性能急剧下降。
带宽受限:自维平台受到专线带宽的限制,一旦攻击流量超过专线带宽,出口即被拥塞,任何手段都无解;托管平台受到IDC清洗能力限制,一旦超过IDC能承受的攻击流量(一般远小于20G),会强制将机器下线。
攻击复杂多变:流量型:UDP Flood,HTTP Flood;连接型:SYN Flood,CC(最难防护);反射型:DNS Flood,NTP Flood。
DDOS攻防专家:DDOS攻防需要扎实的协议分析知识;对常见的攻击行为能快速判断。

从myisam到innodb
1)完整的事务特性支持,获得更高并发的TPS
2)支持crash recovery,myisam不能自动修复,且耗时更久
3)innodb把数据和索引同时放入buffer中,而myisam则只缓存了索引

Nginx Upsync
支持基于consul自动服务发现,解决reload的性能问题,微博采用基于Consul配置中心实现自动发现服务,解决了Reload的性能问题。

电商而言三大核心就是商品、会员、订单中心

作者:AngryFox 分类: Uncategorized May 28th, 2016 暂无评论

如何快速扩容
如何快速缩容
如何提升资源利用率
如何降低成本

私有云平台架构
私有云管理
虚拟化管理
网络管理
硬件管理

混合云
私有云服务(与云厂商合作,专线对接按需创建 会话活动,秒杀等访问量大的业务迁入私有云服务)
流量调度(支持 地域+isp 维度的流量调度 机房级别流量调度与分配 故障一键切换(支持机房和线路级别的故障))
二级CDN(将动态页面静态化,接入二级CDN 根据地域特点搭建云资源节点 调度流量占比,提升用户体验)

图片系统
裁剪
加速
分发
缓存外图缓存

思想
解耦(需求变化快,开发资源少)
保持简单的结构(保持低成本的弹性扩展)
尽量使用云服务(减少维护成本)

作者:AngryFox 分类: Uncategorized May 19th, 2016 暂无评论

系统稳定性
流程规范、理念提升、技术保障、高效工具。
(1)低耦合(绝大部分架构师已熟知并实践),高内聚(不少架构师有可能忽视或无视);
(2)KISS;
(3)Design for Failure;
(4)Automation Everywhere;
(5)SOLID/Elemental Design Patterns/Design Patterns

如高带宽、低延迟、分析、操作、容积以及速度。数据建模的灵活性、性能以及横向可扩展性。
网络连接保活:如何保证消息接收实时性。
(1)找到真正需求,而不是创造[伪需求];
(2)先做出最小可用产品(MVP),然后根据市场反馈再定是继续迭代优化,还是迅速调整方向;
(3)既然很多创业者只缺一个程序员,那就对你的程序员好一点,再好一点。刚开始创业,更需要 full-stack engineer,而不是各种 big title(研发总监、架构师、CTO);
(4)即使 full-stack engineer,也不是真的全能选手,所以,机房/网络/服务器/存储/监控/告警/安全甚至数据库什么的,可以考虑适当交给云计算。
进程保活:尽量保证应用的进程不被Android系统回收。
长连接实现包括几个要素:

a. 网络切换或者初始化时 server ip 的获取。
b. 连接前的 ip筛选,出错后ip 的抛弃。
c. 维护长连接的心跳。
d. 服务器通过长连notify。
e. 选择使用长连通道的业务。
f. 断开后重连的策略。

cloudera(hadoop cluster) + python hive pig(tools)
spark

作者:AngryFox 分类: Uncategorized May 8th, 2016 暂无评论

nginx-1.10.0 stable version has been released, incorporating new features from the 1.9.x mainline branch – including the stream module, HTTP/2, dynamic modules support and more.
The module is experimental

http://nginx.org/en/docs/http/ngx_http_v2_module.html

只需要在 listen 时加上 http2 就可以了,例如:
listen 443 ssl http2;

ssl_certificate server.crt;
ssl_certificate_key server.key;
HTTP/2 的优势

相比 HTTP/1.x,HTTP/2 在底层传输做了很大的改动和优化:

HTTP/2 采用二进制格式传输数据,而非 HTTP/1.x 的文本格式。二进制格式在协议的解析和优化扩展上带来更多的优势和可能。
HTTP/2 对消息头采用 HPACK 进行压缩传输,能够节省消息头占用的网络的流量。而 HTTP/1.x 每次请求,都会携带大量冗余头信息,浪费了很多带宽资源。头压缩能够很好的解决该问题。
多路复用,直白的说就是所有的请求都是通过一个 TCP 连接并发完成。HTTP/1.x 虽然能利用一个连接完成多次请求,但是多个请求之间是有先后顺序的,后面发送的请求必须等待上一个请求返回才能发送响应。这会很容易导致后面的请求被阻塞,而 HTTP/2 做到了真正的并发请求。同时, 流还支持优先级和流量控制。
Server Push:服务端能够更快的把资源推送给客户端。例如服务端可以主动把 JS 和 CSS 文件推送给客户端,而不需要客户端解析 HTML 再发送这些请求。当客户端需要的时候,它已经在客户端了。
HTTP/2 主要是 HTTP/1.x 在底层传输机制上的完全重构,HTTP/2 是基本兼容 HTTP/1.x 的语义的。 Content-Type 仍然是 Content-Type ,只不过它不再是文本传输了。

作者:AngryFox 分类: Uncategorized May 8th, 2016 暂无评论

optimization opportunities:
net/http Request object lifetime isn’t limited by request handler execution time. So the server must create new request object per each request instead of reusing existing objects like fasthttp do.
net/http headers are stored in a map[string][]string. So the server must parse all the headers, convert them from []byte to string and put them into the map before calling user-provided request handler. This all requires unnecessary memory allocations avoided by fasthttp.
net/http client API requires creating new response object per each request.

asthttp并没有完全地解析所有的http请求header数据

type RequestHeader struct {
        //bla.....
	contentLength      int
	contentLengthBytes []byte

	method      []byte
	requestURI  []byte
	host        []byte
	contentType []byte
	userAgent   []byte

	h     []argsKV
	bufKV argsKV

	cookies []argsKV

	rawHeaders []byte
}
argsKV

type argsKV struct {
	key   []byte
	value []byte
}

从[]byte转化为string时是有copy和alloc的,net.http中使用了map[string]string来存储各种其他参数,这就需要alloc,为了达成zero alloc,fasthttp采用了遍历所有header参数来返回,[]byte alloc
net.http的header头对象每次创建新的,而不是循环利用,而且做map[string]string转换

作者:AngryFox 分类: Uncategorized May 7th, 2016 暂无评论

不为用不到的特性付出代价 仅为用到的特性付出最低代价
这是C++的设计原则,也是Rust的设计原则
GC的终极目的是安全地释放内存 • Rust通过Ownership和RAII也能达到此目的,且性能更好
内存安全?
安全地读写内存 • 在限定时间和空间范围内读写内存 • 防止被他人意外修改或释放 • 避免访问空指针和野指针
安全地释放内存 • 在恰当的时机释放 • 确保释放,不遗漏 • 仅释放一次

内存不安全?
• 指针越界访问,意外修改别处内存 • 内存被提前释放,形成野指针,非法读写内存 • 野指针又转化为合法指针,意外修改别处内存 • NULL指针解引用,非法操作 • 并发读写同一内存地址,数据竞争 • 缓冲区溢出、段错误……

实现async的不同机制
callback
generator
async/await
monad

在高并发的分布式系统中,重要点:
1)大系统小做,把一个大的系统拆分成很多小的独立的服务,降低系统的复杂性
2)需要一套成熟的通信框架,来提高开发效率。
3)尽量避免使用多线程,最好是多进程、无锁设计。
4) 做好过载保护、监控和灰度。(这个很重要)

推送系统
1) 接入层性能问题
原来的接入层单台服务器最多接入30W长连接,而且很多业务逻辑也放在了接入层处理,导致接入层性能低下,而且代码很臃肿,维护成本很高,所以我们对接入层做重构,把业务逻辑拆分出来,接入层只做简单的用户接入。所有的业务逻辑都在后端处理。也就是现在比较流行的微服务的架构。
2) 带宽问题
最初我们的系统使用的是文本协议,每次做全网推送都占用了IDC大量的带宽,导致用户访问其他业务非常慢,我们就自定义了一套二进制协议,降低了50%-70%的带宽。
3) 服务化的基础组件
第一点里面提到 我们的一些业务逻辑是和接入层搅在一起的,我们需要把业务逻辑拆分成单独的服务。服务之间的互相调用就需要一套成熟的网络通讯框架。我们就做了一套RPC的框架,来提高开发的效率。最初这套框架用的多线程+同步调用,在实际的使用中发现,多线程有很多坑,各种锁,特别是新员工写代码一不小心就死锁了。而且同步调用的性能并不理想,虽然开了多线程,但是线程又不能开的太多(大家都懂的)。针对以上情况,我们做了第二版的框架,使用了多进程+异步,服务的性能提高了10倍,但是又面对另外一个问题,因为异步,就没有办法避免各种回调,本来很连续的一个业务逻辑流程被打散在了各种回调函数里面,看代码的人非常痛苦,而且很容易产生内存泄露问题,比如:我申请的内存传递到回调函数中,结果忘记释放了(我们发现的内存泄露问题95%都是这样产生的)。
最后,我们参照go语言的特性使用协程来做了第三版的框架,业务开发人员再也不用考虑同步的性能和异步的回调问题。同步调用方式、异步的性能。
4) 存储
引入了redis和mongodb来做缓存和消息存储。
因为redis是有单点问题,我们开发了一套redis集群,一是提高redis的存储容量,二是解决单点的风险。
根据业务形态选择合理的片键,尽量手动分片。
mongodb自带的balancer最好在业务低峰期做。
合适的索引。

微服务提倡的足够小、可独立部署、升级、伸缩和运维确实能够提升系统的敏捷性,满足业务的快速发布和敏捷交付,降低运维成本。

分布式服务框架的关键技术有三点:

1) 底层远程服务调用使用的RPC框架,它负责链路的创建、跨网络通信、消息的发送和接收、消息序列化和反序列化等。
2) 服务的调度和透明化路由,涉及到服务的发布和消费、服务的透明化路由和软负载,以及集群容错等。
3) 服务治理: 服务化之后,如何保障服务线上高效运行,服务发生故障之后如何快速恢复业务,需要一套功能强大和成熟的服务治理体系来保障服务的SLA。

insert,update,delete 

数据变更语句insert,update和delete在它们的实现中非常相似:

<insert
    id="insertAuthor"
    parameterType="domain.blog.Author"
    flushCache="true"
    statementType="PREPARED"
    keyProperty=""
    useGeneratedKeys=""
    timeout="20000">  

<update
    id="insertAuthor"
    parameterType="domain.blog.Author"
    flushCache="true"
    statementType="PREPARED"
    timeout="20000">  

<delete
    id="insertAuthor"
    parameterType="domain.blog.Author"
    flushCache="true"
    statementType="PREPARED"
    timeout="20000">  

属性 	描述
id 	在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType 	将会传入这条语句的参数类的完全限定名或别名。
flushCache 	将其设置为 true,不论语句什么时候被调用,都会导致缓存被清空。默认值:false。
timeout
这个设置驱动程序等待数据库返回请求结果,并抛出异常时间的最大等待值。默认不设置
(驱动自行处理)
statementType
STATEMENT,PREPARED 或 CALLABLE 的一种。这会让 MyBatis使用选择使用 Statement,,PreparedStatement 或 CallableStatement。默认值:PREPARED。
useGeneratedKeys
(仅对insert有用)这会告诉MyBatis使用JDBC的getGeneratedKeys方法来取出由数据
比如:像MySQL和SQL Server 这样的数据库管理系统的自动递增字段)内部生成的主键。
默认值:false。
keyProperty 	(仅对insert有用)标记一个属性, MyBatis会通过getGeneratedKeys或者通过 insert 语句的selectKey子元素设置它的值。默认:不设置。
下面就是 insert,update 和 delete 语句的示例:

<insert id="insertAuthor" parameterType="domain.blog.Author">
    insert into Author (id,username,password,email,bio)
    values (#{id},#{username},#{password},#{email},#{bio})
</insert>
<update id="updateAuthor" parameterType="domain.blog.Author">
    update Author set
        username = #{username},
        password = #{password},
        email = #{email},
        bio = #{bio}
    where id = #{id}
</update>
<delete id="deleteAuthor” parameterType="int">
    delete from Author where id = #{id}
</delete>
它有一些属性和子元素用来处理主键的生成。首先,如果你的数据库支持自动生成主键的字段(比如MySQL和SQL Server),那么你可以设置useGeneratedKeys=”true”,而且设置keyProperty到你已经做好的目标属性上。例如,如果上面的Author表已经对id使用了自动生成的列类型,那么语句可以修改为:
<insert id="insertAuthor" parameterType="domain.blog.Author"
    useGeneratedKeys=”true” keyProperty=”id”>
    insert into Author (username,password,email,bio)
    values (#{username},#{password},#{email},#{bio})
</insert>
MyBatis有另外一种方法来处理数据库不支持自动生成类型,或者可能JDBC驱动不支持自动生成主键时的主键生成问题。
这里有一个简单(甚至很傻)的示例,它可以生成一个随机ID可能你不会这么做,但是这展示了MyBatis处理问题的灵活性,
因为它并不真的关心ID的生成: 

<insert id="insertAuthor" parameterType="domain.blog.Author">
    <selectKey keyProperty="id" resultType="int" order="BEFORE">
        select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1
    </selectKey>
    insert into Author(id, username, password, email,bio, favourite_section)
    values(#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR})
</insert>
在上面的示例中,selectKey元素将会首先运行,Author的id会被设置,然后插入语句会被调用。这给你了一个简单的行为在你的数据库中来处理自动生成的主键,而不需要使你的Java代码变得复杂。 selectKey 元素描述如下: 

<selectKey
    keyProperty="id"
    resultType="int"
    order="BEFORE"
    statementType="PREPARED">
属性	描述
keyProperty 	selectKey 语句结果应该被设置的目标属性。
resultType
结果的类型。MyBatis通常可以算出来,但是写上也没有问题。MyBatis允许任何简单类型用作
主键的类型,包括字符串。
order
这可以被设置为 BEFORE 或 AFTER。如果设置为 BEFORE,那么它会首先选择主键,
设置 keyProperty 然后执行插入语句。如果设置为 AFTER,那么先执行插入语句,然后是
selectKey 元素,这和Oracle 数据库相似,可以在插入语句中嵌入序列调用。
statementType
和前面的相同,MyBatis支持STATEMENT,PREPARED 和CALLABLE 语句的映射类型
,分别代表 PreparedStatement 和CallableStatement 类型。
作者:AngryFox 分类: Uncategorized May 3rd, 2016 暂无评论

示例将代码分为四层,对应到MVP模式中:
Mode:Entities
Presenter:Use Cases+Presenters
View:UI
为了保证每个层都能方便的进行单元测试并和其它层相对独立,将项目分为三个模块,Presentation、Domain和Data。
1)Presentation
Presenters和UI被划分到这一层,但Presenters在这里只是负责将Domain逻辑处理后的数据进行组装并调度UI显示,没有业务处理逻辑。这样将数据逻辑处理划分给Domain可以让Presenter更关注于UI显示的调度,从而避免Present逻辑的冗余。这也是我选择这个工程作为示例的原因。
2)Domain
这里对Data中的数据进行逻辑处理,为Present提供业务逻辑和数据支持。
3)Data
数据仓库。例如,当通过id获取用户数据时,首先会检测用户信息是否已经存储在本地,否则的话就会从服务器获取后在本地缓存。根据上篇博客提到的设计原则,外圆代码逻辑无需关心用户数据是从存储介质、内存还是服务器获取,只需拿到Domain处理好的最终数据进行展示和交互即可。

所谓的mvp,即是(model-处理业务逻辑(主要是数据读写,或者与后台通信(其实也是读写数据)),view-处理ui控件,presenter-主导器,操作model和view)

resenter的出现,将Actvity视为View层,Presenter负责完成View层与Model层的交互。

View 对应于Activity,负责View的绘制以及与用户交互
Model 依然是业务逻辑和实体模型
Presenter 负责完成View于Model间的交互

MVC中是允许Model和View进行交互的,而MVP中很明显,Model与View之间的交互由Presenter完成。还有一点就是Presenter与View之间的交互是通过接口的(代码中会体现)。

作者:AngryFox 分类: Uncategorized May 2nd, 2016 暂无评论

对RPC范式的批评:延迟、缺乏并行性、异常处理以及故障检测等等。Erlang则为分布式提供了第一等的支持,它虽然同样使用了RPC机制,但更倾向于在进程之间使用异步消息传递方式。
CDN
全球接入点 (POPs) 数量
防止分布式拒绝服务(DDOS)攻击
内容失效和传输的时间
API支持
HTTPS支持

go1.7
编译和连接时间;
代码生成
新的后端改成了使用静态单一分配形式(static single assignment,SSA),这与LLVM和其他编译器相同,这样能够对生成的代码启用多项优化。其中包含无用代码消除(dead code elimination)、寄存器分配(register allocation)、栈帧分配(stack frame allocation)等
Hack: 马上上手, 快速搞定, 持续迭代.
特点:非传统,技术驱动, 数据为王 Growth Hack => Growth + Hack

jstorm
性能提升 1. 重新设计数据结构 2. 多级batch机制 3. 增加线程池单独处理反序列化 4. 去掉总发送线程和总接受现场,降低瓶颈 5. 在spout内部读写分离 6. 解决disruptor和spout 空数据cpu空跑问题. 7. 降低采样对性能影响. 8. 优化所有复杂函数, 比如rotatingmap/acker 9. GC调优

Server端性能衡量指标
• 应用响应时间 • 业务性能,吞吐率,成功率 • 服务性能(SQL,NoSQL,API,外部服务…) • 代码效率(追踪,剖析) • 代码质量(错误,异常)

微服务MSA不足
• 复杂度 • 大小限制 • 进程间通信 • 事务 • 测试 • 服务治理 • 可靠性?
集中式负载均衡
3 无感知的降级和分流
2 服务发现
4 统一实时的监控报警
5 提升进程间通信 6 分布式跟踪 7 持续集成 8 自动化弹性部署