Gino Be Funny

阅读随手记 201612

关键字:Ctrip DAL、推荐系统、分布式队列、分布式定时任务、微服务、系统架构、Kafka、DistributedLog、分布式缓存、分布式数据库、Motan、RPC、IDEA、机器学习、深度学习、微信小程序、性能调优、Git、函数式编程、服务化、高性能、高并发、高可用;

携程开源数据库访问框架Ctrip DAL

http://www.infoq.com/cn/news/2016/09/Ctrip-DAL

  • 支持分表分库;
  • 支持多种数据库和多种语言;
  • 有一套管理DAO的界面(Code Gen),但感觉这个很繁琐;

Recommender systems explained

https://medium.com/recombee-blog/recommender-systems-explained-d98e8221f468#.6vi5y036t
http://www.infoq.com/cn/articles/three-recommendation-systems-principle

  • Knowledge based recommender systems:基于属性(物品和用户都具备一些属性),通过这些属性的相关性进行推荐;
  • Content based recommender systems: 基于用户的行为(显式反馈和隐式反馈)推荐类似的物品;
  • Collaborative filtering: 基于近邻算法,考虑最相似的一组用户进行检查,获取最终推荐最多的物品;

分布式队列编程:从模型、实战到优化

http://www.infoq.com/cn/articles/distributed-queue-programme-model-actual-combat-optimization

  • When:同步VS异步;Who:发送者接收者解耦;Where:消息暂存机制;How:如何传递;
  • 抽象模型:点对点模型、生产者消费者模型、发布订阅模型;
  • 挑战:高吞吐量、高可用性、高一致性要求、完整性约束、持久化要求;
  • 生产者优化:内存缓存请求、内存持久化策略(定期、定量写入)、批量写入队列;

基于Mesos的当当作业云Elastic Job Cloud

http://www.infoq.com/cn/news/2016/09/Mesos-Elastic-Job-Cloud

Mesos的核心概念

Mesos的核心概念

  • 蓝色是Mesos的基础组件,由Mesos Master、Mesos Agent和运维界面/API组成;
  • 紫色是Mesos Framework的组成部分。Mesos只有基础组件并不能独立使用,需要注册Framework接收Mesos Master分配的资源并决定如何执行,目前常见的Marathon和Chronos都是Mesos Framework。Framework的两个重要组成是Scheduler和Executor;
  • 红色是Scheduler中两个最重要的回调方法,resourceOffers用于将资源转化为任务并调用Executor执行,statusUpdate用于处理Executor回传的状态;

Mesos带来的好处

  • 作为部署平台,Mesos可以做到应用分发自动化,省去人工部署成本;
  • Mesos可以将资源收集至统一资源池,做到硬件资源与应用一体化,按需分配资源,自动资源回收,减少资源闲置和浪费;

弃用内置Framework,自研Elastic Job Cloud

Elastic Job Cloud

  • 实现应用分发和资源分配,并且是高可用的解决方案;
  • 资源分配静态与动态相结合,常驻与瞬时作业分离处理;
  • Elastic Job 1.X的核心理念仍可沿用,包括分片,以及之前未提及的功能,如多种作业类型,事件统计等;
  • 易于定制化需求开发;

The Hardest Part About Microservices: Your Data

http://blog.christianposta.com/microservices/the-hardest-part-about-microservices-data/
http://www.infoq.com/cn/news/2016/09/Christian-Posta-Micro-service-da

  • What is the domain? What is reality? –理解上下文,使用DDD建立数据模型、画出边界;
  • Where are the transactional boundaries? – 事务边界是业务不可变性的最小原子单元,要让事务边界尽可能小;
  • How should microservices communicate across boundaries? – 事件机制;
  • What if we just turn the database inside out? – 通过Apache Samza构建事件流处理系统;

美团外卖系统架构演进与稳定性的探索

http://www.infoq.com/cn/articles/evolution-and-stability-of-meituan-waimai-architecture

  • 稳定性的架构设计:大系统小做、依赖稳定性原则、设计这个稳定性的时候需要考虑用户的体验;
  • 事前预警: 分层的监控(系统级监控和业务监控)、日志聚合、监控指标可视化;
  • 三种限流的策略:防刷、等待+限时、单机的QPS保护;
  • 总结:你要想稳定性做的非常可靠,灰度、灰度、还是灰度;慢查询往往闯大祸;防御式编程;SOP保平安;你所担心的事一定会发生,而且可能马上会发生;

A Technical Review of Kafka and DistributedLog

http://distributedlog.incubator.apache.org/technical-review/2015/09/19/kafka-vs-distributedlog.html
http://www.infoq.com/cn/articles/technology-comparison-of-kafka-and-distributedlog

Kafka and DistributedLog

MTDDL——美团点评分布式数据访问层中间件

逻辑架构

  • 实现了MySQL动态数据源、读写分离、分布式唯一主键生成器、分库分表、连接池及SQL监控、动态化配置等一系列功能,支持分库分表算法、分布式唯一主键生成算法的高可扩展性,而且支持全注解的方式接入,业务方不需要引入任何配置文件。
  • 分布式ID生成系统Leaf: 基于DB的Ticket服务,通过一张通用的Ticket表来实现分布式ID的持久化,执行update更新语句来获取一批Ticket,这些获取到的Ticket会在内存中进行分配,分配完之后再从DB获取下一批Ticket。
  • 分库分表目前默认使用的是取模算法,分表算法为 (#shard_key % (group_shard_num table_shard_num)),分库算法为 (#shard_key % (group_shard_num table_shard_num)) / table_shard_num,其中group_shard_num为分库个数,table_shard_num为每个库的分表个数。
  • 为了尽可能地方便业务方接入,MTDDL采用全注解方式使用分库分表功能,通过ShardInfo、ShardOn、IDGen三个注解实现。
  • 采用Spring AOP技术对所有DAO方法进行功能增强处理,通过美团点评分布式会话跟踪组件MTrace进行SQL调用数据埋点及上报,进而实现从客户端角度对SQL执行耗时、QPS、调用量、超时率、失败率等指标进行监控。
  • 动态化配置:在Spring容器启动的时候自动注册数据源及分库分表相关配置到美团点评的统一配置中心MCC,在MCC配置管理页面可以进行动态调整,MCC客户端在感知到变更事件后会刷新本地配置;

常见性能优化策略的总结

http://tech.meituan.com/performance_tunning.html

  • 代码:第一步就应该是分析相关的代码,找出相应的瓶颈,再来考虑具体的优化策略;
  • 数据库:SQL调优(慢查询、explain、profile)、架构层面的调优(读写分离、多从库负载均衡、水平和垂直分库分表)、连接池调优(结合当前使用连接池的原理、具体的连接池监控数据和当前的业务量作一个综合的判断);
  • 缓存:分类(本地和分布式)、场景(读多写少、热点数据)、关键点(更新策略、缓存淘汰、缓存击穿);
  • 异步:BlockingQueue+异步线程、消息中间件;
  • NoSQL:如果业务数据不需要和其他数据作关联,不需要事务或者外键之类的支持,而且有可能写入会异常频繁,这个时候就比较适合用NoSQL(比如HBase)。
  • JVM调优:CPU使用率与Load值偏大(thread count以及gc count)、关键接口响应时间很慢(gc time以及gc log中的stop the world的时间)、发生full gc或者old cms gc非常频繁(内存泄露);
  • 多线程与分布式:单机多线程(引入线程池)、多机多线程(调度、拆分和分发);
  • 度量系统:确定指标、采集数据、计算数据,存储结果、展现和分析;

Intellij IDEA 一些不为人知的技巧

http://www.jianshu.com/p/364b94a664ff

  • 用 Control + E 来找到最近访问的文件;
  • 在行中任意位置使用Control + Shift + Enter 来快速补全分号;
  • Intellij IDEA 里面内置了一个 Rest Client,大家可以通过 Control + Shift + A,然后搜索 Rest Client 来找到;
  • 通过 Control + Shift + V 访问历史粘贴板;
  • 使用Language Injection 的功能(Alt + Enter)将一个字符串标记为JSON、正则。HTML等进行编辑;
  • 使用Smart Step Into( Shift + F7)可以选择到底要 Debug 进入哪一个方法;

技术框架与组件使用

http://weibo.com/ttarticle/p/show?id=2309404038032062872510

Motan的模块组成

  • Motan是微博研发的开源RPC服务框架,基于java语言开发,主要特点是轻量级、高性能、高扩展性。Motan提供了实用的服务治理功能,包括服务发现、负载均衡、HA策略、流量控制等。通过SPI机制能够支持不同RPC协议、传输以及序列化协议,并且可以方便的增加不同的filter功能,便于二次开发。
  • RPC(Remote Procedure Call)指远程过程调用,是一种通过网络调用远程过程的协议,简单地说就是能使应用像调用本地方法一样的调用远程的过程或服务。
  • RPC协议只规定了Client与Server之间的点对点调用流程,包括Stub、通信协议、RPC消息解析等部分, 而RPC框架一般是指能够完成服务调用的解决方案,除了具体通信的RPC协议,还包括服务的发现与注销、提供服务的多台Server的负载均衡、服务的高可用等服务治理的功能。Motan就是这样一个RPC框架。
  • Motan中有服务提供方RPC Server,服务调用方RPC Client和服务注册中心Registry三个角色。
  • 注册中心Vintage是基于Group的,server和client必须在相同group下才能进行访问。
  • Motan server:解析配置文件生成对应的protocol信息、打开并监听声明的RPC服务端口、向Vintage(即Registry)注册RPC服务、服务验证通过后打开心跳开关;
  • Motan client: 解析配置文件生成对应的protocol信息、向Registry订阅所需的RPC服务、对每个Server建立初始链接;

分布式缓存架构基础

http://weibo.com/ttarticle/p/show?id=2309404022116222639373&mod=zwenzhang

微博缓存中间件CacheService

  • Memached Multiget-Hole(在Memcached采用数据分片方式部署的情况下,对于multiget命令来说,部署部署更多的节点,并不能提升multiget的承载量,甚至出现效率反而降低):使用多副本的方式扩容、multiget的keys尽可能放在同一个节点上;
  • 反向Cache就是将一个不存在的key放在缓存中,也就是在缓存中存一个空值,减少对DB的穿透。
  • 缓存Fail-Fast:当出现故障节点时,标识故障节点为不可用节点(策略举例:连续N次请求都出现超时,标识M时间段内为不可用),读写不可用节点快速返回。
  • 缓存无过期(缓存中存储全量数据,不存在数据穿透的情况):适合总体数据量很小,但是访问量巨大的业务场景;
  • dog-pile effect狗桩效应 (极热访问的缓存数据失效,大量请求发现没有缓存,进而穿透至DB):从代码层面就要考虑到并发穿透的情况,保证一个进程只有一次穿透;
  • 极热点数据场景(缓存资源遇到性能瓶颈):前端使用local cache, 以缓解后端缓存的压力;考虑引入L1结构,通过部署多组小容量的L1缓存来应对突然的访问量增长;
  • 避免雪崩(缓存服务器宕机等原因导致命中率降低,大量的请求穿透到数据库):缓存高可用、降级和流控、清楚后端资源容量;
  • 数据一致性(CAP)-> 采用数据最终一致性:Master与副本一致性、Cache与Storage一致性、业务各维度缓存数据一致性;
  • 缓存容量规划:考虑请求量、命中率、网络带宽、存储容量、连接数;
  • 微博缓存中间件CacheService:代理层/资源层/客户端/配置中心/集群管理系统;

从优化性能到应对峰值流量:微博缓存服务化的设计与实践

http://weibo.com/ttarticle/p/show?id=2309404013728432540615

Main-HA 双层架构

  • 微博使用的缓存主要是 Memcache 和 Redis,因为 Memcache 的使用场景、容量更大,而且目前推的缓存服务化也是优先基于 Memcache,然后再扩展到 Redis、 ssdcache 等其他缓存;
  • 如果某个时间点,核心业务的多个缓存节点不可用,大量请求穿透会给 DB 带来巨大的压力,极端情况会导致雪崩场景。于是我们引入 Main-HA 双层架构。
  • 对于集群内的扩缩,线上操作最多的是增减 L1 组或扩容 main 层。
  • S4LRU分成四个子 LRU: LRU0-LRU3。 Key miss 或新写入一个 key 时,把这个 key 放在第一层 LRU0,如果后来被命中则移到 LRU1 ;如果在 LRU1 又一次被命中则移到 LRU2,依此类推,一直升级到 LU3。如果它四次以上命中,就会一直把它放在 LU3。如果发现 LU3 的数据量太多需要 evict,我们先把待 evict 的 key 降级到 LU2 上,如此类推。同时每个 kv 有过期时间,如果发现它过期就清理。
  • LS4LRU 是在 S4LRU 的基础上增加一个分级的过期时间,每个 KV 有两个过期时间 exp1 和 exp2。比如说某业务, exp1 是一秒, xep2 是三秒, LS4LRU 被命中的时候,如果发现它是在一秒内的数据,则直接反给客户端的,如果是在 1 秒到 3 秒的时候,则会首先返回到客户端,然后再从异步获取最新的数据并更新。如果是 3 秒以上的,就直接去清理,走 key miss 流程。

海量数据存储基础

http://weibo.com/ttarticle/p/show?id=2309404025046866781970&mod=zwenzhang

  • 关系型数据库:局限于服务器性能、局限于数据复杂度、常见的SSD磁盘服务器,单机读取性能可达万级/s;
  • NoSQL(Not only SQL)数据库:存储非结构化数据、半结构化数据、单机QPS在10万级别;
  • 微博平台核心业务的数据都存储在MySQL上,目前具备千台规模的集群,单个核心业务数据突破千亿级,单个核心业务QPS峰值可达10万级每秒,写入也是万级每秒。
  • 从单机到集群的架构变迁:SQL优化,硬件升级-》垂直拆分-》读写分离-》水平拆分
  • 分布式数据库设计:hash拆分方式、时间拆分方式
  • 当一台服务器宕机怎么办:Slave宕机(切换、扩容、降级);Master宕机(快速下线master提升slave为master);
  • redis过期机制:被动过期、主动过期(volatile-lru、volatile-ttl、volatile-random、allkeys-lru、allkeys-random);
  • 定制CounterService:修改hash table为增量扩展式的hash tables、废弃expire;
  • 分布式Redis架构如何实现高可用:采用M-S高可用方案、服务域名化是必要的;

微博平台采用如下几个层级的组建来进行分布式数据库操作:

分布式数据库操作

分布式架构下的redis client访问:

分布式Redis访问

Java性能调优工程的几点建议

http://www.infoq.com/cn/news/2016/10/javaPerformance-guide-byMonica

  • 能优化工程由两部分组成:性能需求分析及规划、性能结果分析。两者构成闭环,使得性能得到不断的提升。
  • 需要站在用户的角度去思考QoS;将QoS标准量化为可测量的指标,即SLA服务等级协议;然后对SLA性能指标进行定义、梳理并排列优先级(吞吐量、响应时间、容量、请求足迹、CPU使用率等)。
  • 性能调优执行的两种实现方式:自上而下、自下而上。
  • 不论哪一种方向,均可以分为四步:第一步监控、第二步归纳、第三步分析、第四步调优和应用。

机器学习:发展与未来 – 周志华

http://www.leiphone.com/news/201610/rZ9EHIpeSwBv2Tvq.html

机器学习

  • 现在是大数据时代,但是大数据不等于大价值。
  • 人工智能的三个阶段:推理期(自动定理证明系统)、知识器(专家系统)、学习期(机器学习);
  • 计算学习理论中最重要的一个理论模型就是概率近似正确模型(PAC);
  • 从技术层面来看,深度学习其实就是很多层的神经网络,最著名的深度学习模型叫做卷积神经网络(CNN);
  • 提升模型的复杂度可以提升学习能力,增加模型深度比宽度更有效,但提升模型的复杂度并不一定有利,因为存在过拟合和计算开销大的问题。
  • 深度学习最重要的作用是表示学习;
  • 传统的机器学习任务大都是在给定参数的封闭静态环境中,而现在正在慢慢转向开放动态环境。
  • 其实机器学习的形态就是算法 + 数据。
  • 学件(Learnware)= 模型(model)+规约(specification);“可重用”的特性能够获取大量不同的样本、“可演进”的特性可以适应环境的变化、“可了解”的特性能有效地了解模型的能力;

Git from the inside out

https://codewords.recurse.com/issues/two/git-from-the-inside-out

一篇非常有意思的介绍Git原理的文章,虽然比较长,但图文结合,花个半个小时能看懂。

Core Functional Programming Concepts

https://thesocietea.org/2016/12/core-functional-programming-concepts/

  • Functions are Pure:幂等性、无副作用;
  • Functions are First-Class and can be Higher-Order:一等公民、高阶函数;
  • Variables are Immutable:变量不可变性;
  • Functions have Referential Transparency:如果程序中任意两处具有相同输入值的函数调用能够互相置换,而不影响程序的动作,那么该程序就具有引用透明性;
  • Functional Programming is Based on Lambda Calculus:Lambda算子(匿名、柯里化)

The JVM Architecture Explained

https://dzone.com/articles/jvm-architecture-explained

JVM Architecture

  • Class Loader Subsystem: Boot Strap ClassLoader/Extension ClassLoader/Application ClassLoader;Linking: Verify -> Prepare -> Resolve;
  • Runtime Data Area: Method Area/Heap Area/Stack Area/PC Registers/Native Method stacks;
  • Execution Engine: Interpreter/JIT Compiler/Garbage Collector;

One Sure-Fire Way to Improve Your Coding

https://changelog.com/posts/one-sure-fire-way-to-improve-your-coding

  • 代码写少读多,多读代码能显著提升编码水平;
  • 读什么:正在用的插件、库和框架;惊艳你的代码;崇拜的大神的代码;从小项目开始;
  • 怎么读:看整体项目结构、给代码加注释、跑自带的测试用例、尝试更改或添加特性、不断尝试;

Best Practices for Building a Microservice Architecture

http://www.vinaysahni.com/best-practices-for-building-a-microservice-architecture

The Platform

  • Your platform is a set of standards combined with supporting tools (统一控制面板管理)

Service Essentials

  • Independently develop & deploy services (独立开发部署、谨慎对待共享库)
  • Services should have their own private data (公用数据库导致服务不独立、共享数据库服务器)
  • Keep Services small enough to stay focused and big enough to add value (低耦合、高内聚、单一边界上下文)
  • Store data in databases, not ephemeral service instances (无状态服务实例、便于扩容和负载均衡)
  • Eventual consistency is your friend (最终一致性带来松耦合、便于使用异步通信)
  • Offload work to asynchronous workers whenever possible (异步通信加快响应、降低错误、便于扩容)
  • Keep helpful documentation for all services in a common place (统一维护接口文档)
  • Distribute work with load balancers (使用客户端的负载均衡代替接收方的负载均衡)
  • Aggregation services on network boundaries can translate for the outside world (聚合服务负责收集来自其他服务的数据,处理任何特殊的编码或压缩要求)
  • Layer your security and don’t write your own crypto code! (分层式安全、使用自动化的安全更新、加固底层操作系统、不要自行编写加密代码)

Service Interactions

  • Transport data over HTTP, serialized using JSON or protobuf (同步通信用HTTP、异步用消息队列、用JSON或protobuf序列化)
  • For HTTP services, 500 series errors or timeouts mean the service is unhealthy(统一服务异常码)
  • APIs should be simple and effective (使用优雅的面向资源的REST接口设计)
  • A service discovery mechanism makes it easy for services to find each other (服务注册、服务发现、负载均衡+DNS)
  • Prefer decentralized interactions over centralized orchestrators (去中心化的交互耦合更低)
  • Version all APIs, colocating multiple versions within the same service instances (支持多版本的接口)
  • Use limits on resources to fail fast before a service gets overloaded (快速失败)
  • Connection pools can reduce downstream impact of sudden request spikes (平滑化请求、相互隔离)
  • Timouts minimize impact from downstream delays and failures (更短的超时避免级联失败)
  • Be tolerant of unrelated downstream API changes (向前兼容的接口变更)
  • Circuit breakers give downstream services a break during tough times (断路器直接失败)
  • Correlation IDs help you track requests across service logs (为请求生成唯一标识便于跟踪)
  • Make sure you can guarantee eventual consistency (稍后修复、每块数据都应该有一个单一数据源)
  • Authenticating all API calls provides a clearer picture of usage patterns
  • Auto retry failed requests with random retry intervals (使用随机化的重试避免惊群效应)
  • Only talk to a services through exposed and documented APIs
  • Economic forces encourage efficient usage of available resources
  • Client libraries can handle all the basics, so you can focus on what matters

Development

  • Use a common source control platform for all services (每个服务都该有自己的代码库)
  • Either mimic prod in dev or use isolated cloud based dev environments (本地开发和运行的服务与云中运行的隔离环境结合)
  • Push working code to mainline often (尽快将开发中的代码与主线分支进行集成)
  • Release less, release it faster (持续交付的目标在于更快速地发布小规模变更)
  • Warning: shared libraries are painful to update (无法控制何时将共享库的更新部署到使用它的服务上是使用共享库带来的最大挑战,最佳做法是发布弃用时间表)
  • Your service templates should cover the fundamentals out of the box (除了核心业务逻辑,服务还管理一系列其他附加任务,例如服务注册、监控、客户端负载均衡、限制管理、断路。团队应能通过这些模板快速实现服务自举以处理所有常见任务,并与平台进行恰当集成。)
  • Simple services are also easy to replace

Deployment

  • Use a system image for a deployment package (标准化的部署程序包是自动化部署流水线中重要的组成部件)
  • Have a way to automatically deploy any version of any service to any environment (零停机更新)
  • Feature flags decouple code deployment from feature deployment (有效地实现代码部署和功能部署间的解耦)
  • Configuration should be managed outside of the deployment package

Operations

  • Manage all logs in one place (任何日志都不应存储在实例中)
  • Use a common monitoring platform for all services (监控解决方案必须能将不同实例的衡量值汇总在一起)
  • Stateless services are easy to auto scale (很多微服务平台为实例数量的处理提供了声明性接口,这种功能非常易用)
  • Dependent services that don’t run on your platform also need automation

People

  • Service teams develop, deploy & operate their own services (服务团队需要拥有、运维并完善自己构建的服务)
  • Teams should be autonomous in daily operations (拥有这些服务的团队必须具备开发、部署,以及运维这些服务所需的全部技能和工具)

Best Practices for Designing a Pragmatic RESTful API

http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api

  • An API is a user interface for a developer - so put some effort into making it pleasant
  • Use RESTful URLs and actions
  • Use SSL everywhere, no exceptions
  • An API is only as good as its documentation - so have great documentation
  • Version via the URL, not via headers
  • Use query parameters for advanced filtering, sorting & searching
  • Provide a way to limit which fields are returned from the API
  • Return something useful from POST, PATCH & PUT requests
  • HATEOAS isn’t practical just yet
  • Use JSON where possible, XML only if you have to
  • You should use camelCase with JSON, but snake_case is 20% easier to read
  • Pretty print by default & ensure gzip is supported
  • Don’t use response envelopes by default
  • Consider using JSON for POST, PUT and PATCH request bodies
  • Paginate using Link headers
  • Provide a way to autoload related resource representations
  • Provide a way to override the HTTP method
  • Provide useful response headers for rate limiting
  • Use token based authentication, transported over OAuth2 where delegation is needed
  • Include response headers that facilitate caching
  • Define a consumable error payload
  • Effectively use HTTP Status codes

服务化框架技术选型与京东JSF解密

http://mp.weixin.qq.com/s/hureIGrLVKO7FLDOWdNjWA

基本的服务化框架包括如下模块:统一的RPC框架,服务注册中心,管理平台。

RPC框架选型

需要考量的因素:

  • 代码规范:例如是对已有代码透明,还是代码生成;
  • 通讯协议:例如是TCP还是HTTP;
  • 序列化协议:例如是二进制还是文本,是否需要跨语言,性能;
  • IO模型:异步/同步,阻塞/非阻塞;
  • 负载均衡:客户端软负载,代理模式,服务端负载。

另外如果是从开源里面选择,那么我们还需要考量:

  • 成熟度:包括学习成本,社区热度,文档数,是否有团队维护,稳定性(盲目追求的不一定是最适合);
  • 可扩展性:是否有SPI支持扩展,是否支持上下兼容;
  • 跨语言:是否支持跨语言;
  • 性能:要想作为RPC框架,性能一般都不会太差。

RPC框架比较

  • 如果需要与前端交互的,适合短链接、跨语言的RPC框架,例如RESTful、gRPC等;
  • 如果纯粹后台交互的,适合长链接、序列化为二进制的RPC框架,例如thrift、dubbo等更高效;
  • 如果是小公司,新公司从头开始推广服务化框架的,可以选择规范化的RPC框架,例如thrift、RESTful、gRPC;
  • 如果是已有大量业务代码的再推广服务框架的,那么最好选择无代码入侵的RPC框架,例如dubbo、RESTful。

注册中心选型

选择注册中心基本要考量:

  • 服务注册:接收注册信息的方式;
  • 服务订阅:返回订阅信息的方式,推还是拉;
  • 状检测:检测服务端存活状态。

如果是从开源里面选择,那么还需要考量:

  • 成熟度:包括学习成本,社区热度,文档数(盲目追求的不一定是最适合);
  • 维护成本:注册中心维护;
  • 数据解构:是否能快速定位结果,是否能遍历;
  • 性能和稳定性;
  • CAP原则:CP(关注一致性)还是AP(关注可用性)。

注册中心比较

  • 规模小选择CP,RPC框架可以直接接入数据源;
  • 规模大选择AP, RPC框架不可以直接接入数据源;
  • 存在跨机房,跨地域的尽量不要选有强一致性协议的注册中心;
  • RPC框架必须要有注册中心不可用的容灾策略;
  • 服务状态检测十分重要。

完善的服务化框架

服务化框架

  • 接口文档管理:提供一个接口文档管理以及接口查询的入口。这里可以定义接口的文档,包括接口描述,方法定义,字段定义。可以定义接口的SLA,包括支持的并发数,tp99多少,建议配置是什么。
  • 配置中心:这里说的配置主要指的是服务相关的一些配置。配置包括分组配置、路由策略、黑白名单、降级开关、限流信息、超时时间、重试次数等等,任何可以动态变更的所有数据。
  • 监控中心:监控服务关注接口维度,实例维度的数据。RPC框架可以定时上报调用次数,耗时,异常等信息。监控中心可以统计出服务质量信息,也可以进行监控报警。
  • 分布式跟踪:区别于监控中心,以调用链的模式对服务进行。RPC框架作为分布式跟踪系统的一个天然埋点,可以很好的进行一个数据输出。
  • 服务治理(重点):服务路由、调用授权、动态分组、调用限流、灰度部署、配置下发、服务降级;
  • 网关:RPC框架大部分场景都是自己调用的,网关可以提供如下功能:统一的鉴权服务、限流服务、协议转换、Mock(服务测试,降级等)、其它一些统一处理逻辑(例如请求解析,响应包装)。
  • 服务注册中心Plus:需要逻辑处理能力,例如对数据进行筛选过滤整合,计算服务路由等功能
    同时还需要有与RPC框架交互的功能。
  • 管理端Plus:管理端除了之前的简单服务管理功能外,还需要提供配置信息展示,监控信息展示,各种维度的数据展示。

京东实践

JSF

JSF注册中心

  • 京东的注册中心是自研的,基于DB做的数据最终一致;
  • 注册中心主要实现的就是服务列表的注册订阅推送,服务配置的获取下发,服务状态的实时查看等功能;
  • 注册中心节点是无状态的,可水平扩展的;
  • 每个机房部署多个注册中心节点。同机房的RPC框架会优先连本机房的注册中心节点;
  • 引入Index服务概念:该服务就是一个最简单HTTP的服务,用于找注册中心节点,RPC框架会优先连该服务拿注册中心地址,这样子的好处是注册中心地址变化后,RPC框架不用修改任何设置;
  • 注册中心内存有服务列表全量缓存,连不上数据库也保证可读;
  • 数据库的数据结构更适合各种维度展示、过滤、分析等,例如根据分组/IP/应用/机房等不同维度;
  • 注册中心就是个JSF服务,监控到压力大即可进行动态水平扩展,dogfooding,注册中心其实是第一个JSF接口;
  • 服务列表推送逻辑改进:例如原来100个Provider,现在加1个节点,之前的SAF是需要下发101个节点,自己判断加了哪个节点,进行长链接建立;现在的改进是:修改为下发一个add事件,告知RPC框架加了1个节点,RPC框架进行长链接建立;这样做大大减少了推送的数据量;
  • 注册中心与RPC框架可各种交互:注册中心和RPC框架是长链接,而且JSF是支持Callback的,注册中心可以调用RPC框架进行服务列表变化之外的操作;例如查看状态,查看配置,配置下发等。

JSF RPC框架

JSF RPC框架

JSF的RPC框架主要分为图中的几个模块,下面大概列下一些功能特性:

  • Config:Spring/API/Annotation
  • Proxy: Javassist/JDK
  • Invoker/Filter:内置+自定义,Filter可扩展
  • Client:Failover(默认)/FailFast/TransportPinpoint/MultiClientProxy
  • 调用方式:同步(默认)/异步并行/异步回调/Callback/泛化
  • Loadbalance:Random(默认)/Roundrobin/ConsistentHash/ LocalPreference/LeastActiveCall
  • 路由:参数路由,分组路由,(IP级别路由逻辑在注册中心做)
  • 连接维护:可用/死亡/亚健康
  • 协议:JSF(默认)/SAF(dubbo)/HTTP/Telnet/HTTP2
  • 第三方:REST/Webservice
  • 序列化:MsgPack(默认)/Hessian/Json/Java/protobuf(c++)
  • 压缩:Snappy/LZMA
  • 网络:基于Netty4.0,长连接复用
  • 线程模型:BOSS+WORKER+BIZ
  • 容灾:本地文件
  • 请求上下文:IP,参数,隐式传参
  • 事件监听:响应事件,连接事件,状态事件
  • 分布式跟踪支持:进行数据埋点

JSF管理平台

提供强大管理功能,包括服务管理,监控管理,注册中心管理等功能。

高性能高并发系统的稳定性保障

https://mp.weixin.qq.com/s/YMgIwaz8YC_zNPh_Jf98HA

性能、并发、稳定性三者关系

  • 高性能:高吞吐量、低延时;吞吐量包括QPS, TPS,OPS等;
  • 并发:并不是越高越好,需要考虑TP99;
  • 用户角度:系统是个黑盒,复杂系统中的任何一环到会导致稳定性问题。
  • SLA:在某种吞吐量下能提供TP99为n毫秒的服务能力。
  • 降低延时,会提高吞吐量,但是延时的考核是TP99这样的稳定的延时。

如何改善延时

  • 关键路径:“28原则”(20%的代码影响了80%的性能问题,抓重点)、“过早优化是万恶之源”。不同解读;
  • 优化代码:空间换时间:各级缓存;时间换空间:比如传输压缩,解决网络传输的瓶颈;多核并行:减少锁竞争;lesscode;各类语言、框架、库的trick;算法+数据结构,保持代码的清晰、可读、可维护和扩展;
  • 通过性能测试和监控找出瓶颈;

metric

  • 内存分配: 显式分配器(jemalloc/tcmalloc代替默认的ptmalloc)、隐式分配器(JVM GC的各种调优)、是否使用hugepagen预分配和重用(Netty的Pooled ByteBuf)、减少拷贝(new ArrayList(int), new StringBuilder(int));
  • 减少系统调用:批处理:(buffer io,pipeline)、使用用户态的等价函数:(gettimeofday ->clock_gettime )、减少锁竞争、RWMutex 、CAS、Thread local、最小化锁范围、最小化状态、不变类;
  • 减少上下文切换:触发(中断、系统调用、时间片耗尽、IO阻塞等)、危害(L1/L2 Cache Missing,上下文保存/恢复)、单线程、ThreadPool的配置;
  • 网络:内核TCP Tuning参数和SocketOption、TCP Socket连接池、网络I/O模型、传输压缩、编解码效率、超时心跳和重试机制;

如何提高吞吐量

  • 复制:通过复制提高读吞吐量、容灾、异构;通过数据分片提高写吞吐量;程序双写(同步双写、异步双写、Change Data Capture如Canal);底层存储复制机制;
  • 扩容:扩容规划;扩容checklist、应用扩容、垂直扩容、水平扩容;
  • 异步化:解耦利器、削峰填谷、页面异步化、系统异步化、JMQ、状态机(worker)+DB、本地队列、集中式缓存队列;
  • 缓存:多级缓存、缓存前置、一致性延迟权衡、缓存主节点负责写、通过CDC监听数据库binlog主动更新缓存、CPU不是瓶颈,网络才是、优化编码,减少尺寸、优化操作、优化拓扑;

如何保障稳定性

  • 提高可用性:衡量指标(几个9)、减少故障、减少故障修复时间、冗余复制灾备切换、快速切换、监控;
  • 分组和隔离:网络流量隔离、业务系统隔离、流量分组、存储的分组;
  • 限流:谨慎使用、区分正常流量和超预期流量、读少限,写多限、客户端配合限流、不同分组的限流阈值、多层限流;
  • 降级:保证用户的核心需求、需要有预案和开关、非关键业务屏蔽、业务功能模块降级、数据降级(动态降级到静态,远程服务降级到本地缓存);
  • 监控和故障切换:网络流量;操作系统指标;服务接口调用量、TP99、错误率…;日志;业务量变化;

小结

高性能高并发总结

如何更好的设计RESTful API

https://zhuanlan.zhihu.com/p/24592119

  • 你的API越简单明了,使用的人就越多;
  • HTTP动词GET(SELECT):从服务器检索特定资源,或资源列表。
  • HTTP动词POST(CREATE):在服务器上创建一个新的资源。
  • HTTP动词PUT(UPDATE):更新服务器上的资源,提供整个资源。
  • HTTP动词DELETE(DELETE):从服务器删除资源。
  • HTTP动词PATCH (UPDATE):更新服务器上的资源,仅提供更改的属性。
  • HTTP动词HEAD - 检索有关资源的元数据,例如数据的哈希或上次更新时间。
  • HTTP动词OPTIONS - 检索关于客户端被允许对资源做什么的信息。
  • 版本控制:一个好的RESTful API设计将跟踪URL中的版本;
  • 分析:跟踪客户端使用的API的版本/端点;
  • 将内容设为API根目录是个好主意;
  • 端点是您的API中指向特定资源或资源集合的URL,当引用每个端点可以做什么时,您需要列出有效的HTTP动词和端点组合。
  • 当客户端请求对象列表时,请务必为它们提供符合所请求条件的每个对象的列表。然而,重要的是,您确实为客户端提供了指定某种过滤/结果限制的能力。
  • 作为RESTful API,使用正确的HTTP状态代码非常重要;他们是一个标准!
  • 认证:OAuth 2.0提供了一个很好的方法。对于每个请求,您可以确定知道哪个客户正在发出请求,代表他们请求哪个用户,并提供一种(大部分)标准化的方式来过期访问或允许用户撤消来自客户端的访问权,需要第三方客户端知道用户登录凭据。
  • 内容类型:目前,最令人兴奋的API提供来自RESTful接口的JSON数据。
  • 超媒体API:超媒体API很可能是RESTful API设计的未来。超媒体API概念的工作方式与人类相同。请求API的根返回一个URL列表,它可能指向每个信息集合,并以客户端可以理解的方式描述每个集合。为每个资源提供ID并不重要(或必需),只要提供了一个URL即可。

微信小程序实战,从入门到弃坑

http://www.jianshu.com/p/4433d46e6235

  • 微信小程序的内容部分是hybrid模式,并非原生;
  • 一个完整的微信小程序是由一个App实例和多个Page实例构成,其中App实例表示该小程序应用,多个Page表示该小程序的多个页面。
  • 微信小程序并没有提供自定义组件的方式,这就导致微信小程序在开发较复杂应用时,可能会比较艰难。
  • 两种配置文件:app.json(应用的全局配置文件)、page.json(页面的全局配置文件);
  • 两个核心函数:App() (小程序注册入口,全局唯一)、Page() (页面注册入口);
  • 生命周期及调用流程:

生命周期及调用流程

  • 小程序虽然是hybrid模式,但并不使用HTML渲染。WXML支持数据绑定、条件渲染、循环、模块化等功能。但问题却不少:不能跨浏览器、富文本解析困难,iframe视频不支持,没办法外链跳转。
  • 页面间的跳转见下表:

页面跳转方式

  • 事件绑定:
// bindtap 和 catchtap的区别在于
// bindtap 不会阻止事件冒泡
// catchtap会冒泡事件冒泡
<view id="tapTest" data-hi="WeChat" bindtap="tapName"> Click me! </view>
<view id="tapTest" data-hi="WeChat" catchtap="tapName"> Click me! </view>

// 绑定的函数tapName只是一个函数名称,默认接受一个event对象作为参数
Page({
  tapName: function(event) {
    console.log(event)
  }
})

Java 模块化技术演进和对现有应用微服务化的意义

https://mp.weixin.qq.com/s/7H71uPSKcb2hVam7GU0T6g

  • Java模块化需求:语言定义粒度缺失的一环、顺序加载带来的问题、多版本组件部署;
  • Java模块化的实现:OSGI、Jigsaw、JBoss Module;
  • Java语言的模块化:Jigsaw项目、Java Platform Module System(JSR 376)、推迟到Java9时发布、JDK9 EA 111合并入Jigsaw;
  • JDK 9模块化实例:

JDK 9模块化示意图形

JDK 9模块化代码范例

  • 3种模块化实现特性比较
    3种模块化实现特性比较

  • 模块化技术对微服务的意义:设计更加灵活、模块化是必须的基础设施、和容器技术配合(运用Docker的层叠式文件系统、Kubernetes自动扩展机制的结合)

  • 开发架构的变化:应用架构按照层次进行模块化改造、语言级进行支持、逐步适应、长期的过程;

京东亿级商品搜索核心技术解密

http://mp.weixin.qq.com/s/N2va4w1XERoEIh7ZwT4AUQ

京东商品搜索引擎是搜索推荐部自主研发的商品搜索引擎,主要功能是为海量京东用户提供精准、快速的购物体验。

自身显著的业务特点:结构化的商品数据、极高的召回率要求、商品信息的及时更新、逻辑复杂的商品业务、用户购物的个性化需求;

系统架构分为四个部分:1. 爬虫系统、2. 离线信息处理系统、3. 索引系统、4. 搜索服务系统。

京东商品搜索引擎的整体架构

从上到下共分为3层:

  • 最上层是由搜索的前端UI层,负责页面展示。
  • 中间层是由搜索索引服务、SUG搜索、相关搜索、划词服务和兜底服务组成。其中,SUG搜索提供输入框下拉提示词功能;相关搜索提供与query相关的其他搜索词服务;划词服务提供去除query部分词的功能;兜底服务用于索引服务异常情况下提供托底,保证用户基本的搜索可用。
  • 最下层是索引生产端,主要功能是对接商品、库存、价格、促销、仓储等众多外部系统,整合相关数据生产全量和增量数据的索引,为在线检索服务集群提供全量索引和实时索引数据。

  • 爬虫系统:利用大数据平台的数据库抽取接口和中间件系统,实现了站内商品爬虫系统,用来抽取数据库中的商品信息和及时发现变化的商品信息。

  • 离线信息处理系统:主要功能是用来建立商品搜索引擎的待索引数据,包括全量待索引数据和增量待索引数据。对来源分散的数据在商品维度进行合并,生成“商品全量待索引宽表”。该表不仅应用于搜索引擎服务,还同时应用于个性化推荐等其他产品服务当中。但是仅生成宽表是无法完成搜索引擎的索引需求的,因此我们利用Hadoop/MapReduce计算框架对宽表数据进行清洗,并且依照离线业务逻辑规则对数据进行二次“加工”,最终生成一份全量待索引数据。对于增量索引,采用和全量索引类似的方法对数据进行处理,生成增量待索引数据。为了保证增量数据的及时性和准确性,离线信息处理系统会实时调用各商品信息接口获取数据,完成增量待索引数据的在线组装和生产。
  • 索引系统:索引系统是商品搜索引擎的核心,主要功能是把以商品为维度进行存储的待索引数据,转换成以关键字为维度进行存储的数据,用于搜索引擎上层服务进行调用。
  • 搜索服务系统:Query Processor服务(用户查询意图分析)、User Profile服务(查询用户标签)、detail服务(结果包装、基于缓存云实现的商品信息KV查询服务)、检索服务进行分片化处理;

搜索服务流程

  • 进一步优化:多级缓存策略、截断策略、均匀分片策略、业务优化;
  • 搜索技术的新发展:场景搜索、图像搜索;

解读2016之深度学习篇:开源深度学习框架发展展望

http://www.infoq.com/cn/articles/interpretation-of-2016-deeplearning

  • 单台机器CPU -> 专门的图形处理器(Graphics Processing Unit,GPU)-> 通用图像处理器(General Purpose GPU,GPGPU);
  • 大量的研究表明:增加训练样本数或模型参数的数量,或同时增加训练样本数和模型参数的数量,都能够极大地提升最终分类的准确性;
  • 近年来,存储设备和网络在性能方面的提升远超CPU,CPU性能瓶颈极大地限制了分布式环境下,单台节点的处理速度。许多优秀的开源深度学习框架都在尝试将开源大数据处理技术框架如Spark和GPGPU结合起来,通过提高集群中每台机器的处理性能来加速深度学习算法模型的训练。
  • 深度学习提升性能的三种方式:纵向扩展(给机器加GPU)、横向扩展(通过集群训练模型)及融合扩展(在分布式的基础上,给每个集群中的Worker节点加GPU);
  • 单机开源深度学习框架:Theano(蒙特利尔理工学院)、Torch(Facebook 和 Twitter主推)、TensorFlow(Google开源的)、Caffe(加州大学伯克利分校)、CNTK(微软开源的);
  • 分布式开源深度学习框架:DSSTNE(亚马逊开源的)、Paddle(百度开源的)、SparkNet(AMPLab开源的)、Deeplearning4J(Skymind开源的)、Caffe On Spark(Yahoo开源的)、Tensorflow on Spark(Arimo)、TensorFrames(Databricks开源的)、Angel(腾讯开源的);
  • 开源深度学习框架的发展有以下几个趋势:a.分布式深度学习框架特别是构建在Hadoop生态体系内的分布式深度学习框架(基于Java或Scala语言实现)会越来越流行,并通过融合扩展的方式加速深度学习算法模型的训练。b.在分布式深度学习方面,大数据的本质除了常说的4V特性之外,还有一个重要的本质那就是Online,数据随时可更新可应用,而且数据本质上具备天然的流式特征,因此具备实时在线、模型可更新算法的深度学习框架也是未来发展的方向。c. 当待训练的深度学习算法模型参数较多时,Spark与开源分布式内存文件系统Tachyon结合使用是提升性能的有效手段。

技术人员的发展之路

http://coolshell.cn/articles/17583.html

  • 一个重要阶段和标志:人生中的一个非常重要的阶段——20到30岁;这个阶段的首要任务,就是提升自己学习能力和解决难题的能力。这是一个非常非常关键的时间段!这个时间段几乎决定着你的未来。
  • 高效的学习能力和解决问题的能力;
  • 个人发展的三个方向:在职场中打拼、去经历有意义有价值的事、追求一种自由的生活;

免责声明:相关链接版本为原作者所有,如有侵权,请告知删除。

Gino Zhang wechat
扫一扫,关注我的微信公众号