Tuesday, September 29, 2015

Microservices Architecture



Pattern: Microservices Architecture
Forces
There is a team of developers working on the application
New team members must quickly become productive
The application must be easy to understand and modify
You want to practice continuous deployment of the application
You must run multiple copies of the application on multiple machines in order to satisfy scalability and availability requirements
You want to take advantage of emerging technologies (frameworks, programming languages, etc)

Solution
Architect the application by applying the Scale Cube (specifically y-axis scaling) and functionally decompose the application into a set of collaborating services. Each service implements a set of narrowly, related functions.

Services communicate using either synchronous protocols such as HTTP/REST or asynchronous protocols such as AMQP.

Services are developed and deployed independently of one another.

Each service has its own database in order to be decoupled from other services. When necessary, consistency is between databases is maintained using either database replication mechanisms or application-level events.

Resulting context
Each service can be deployed independently of other services - easier to deploy new versions of services frequently

Easier to scale development. It enables you to organize the development effort around multiple teams. Each (two pizza) team is responsible a single service. Each team can develop, deploy and scale their service independently of all of the other teams.

Improved fault isolation.
Eliminates any long-term commitment to a technology stack

Developers must implement the inter-service communication mechanism.
Implementing use cases that span multiple services without using distributed transactions is difficult
Implementing use cases that span multiple services requires careful coordination between the teams

Each service should have only a small set of responsibilities.
http://smartbear.com/all-resources/articles/what-is-microservices-architecture/
Cons
  • Due to distributed deployment, testing can become complicated and tedious
  • Increasing number of services can result in information barriers
  • The architecture brings additional complexity as the developers have to mitigate fault tolerance, network latency, and deal with a variety of message formats as well as load balancing
  • Being a distributed system, it can result in duplication of effort
  • When number of services increases, integration and managing whole products can become complicated
  • In addition to several complexities of monolithic architecture, the developers have to deal with the additional complexity of a distributed system
  • Developers have to put additional effort into implementing the mechanism of communication between the services
  • Handling use cases that span more than one service without using distributed transactions is not only tough but also requires communication and cooperation between different teams
Pattern: API Gateway
Forces
The granularity of APIs provided by microservices is often different than what a client needs. Microservices typically provide fine-grained APIs, which means that clients need to interact with multiple services.

Resulting context
Insulates the clients from how the application is partitioned into microservices
Insulates the clients from the problem of determining the locations of service instances
Insulates the clients from how the application is partitioned into microservices
Insulates the clients from the problem of determining the locations of service instances

On the JVM, NIO-based libraries such as Netty, Spring Reactor, etc. make sense. NodeJS is another option.
http://microservices.io/patterns/client-side-discovery.html
When making a request to a service, the client obtains the location of a service instance by querying a Service Registry, which knows the locations of all service instances.

Netflix OSS provides a good example of client-side discovery:

Eureka is a Service Registry
Ribbon Client is an HTTP client that queries Eureka to route HTTP requests to an available service instance

http://microservices.io/patterns/server-side-discovery.html
When making a request to a service, the client makes a request via a router (a.k.a load balancer) that runs at a well known location. The router queries a service registry, which might be built into the router, and forwards the request to an available service instance.

http://martinfowler.com/articles/microservices.html
Characteristics of a Microservice Architecture
    Componentization via Services
    Organized around Business Capabilities
    Products not Projects
    Smart endpoints and dumb pipes
    Decentralized Governance
    Decentralized Data Management
    Infrastructure Automation
    Design for failure
    Evolutionary Design
Change control doesn't necessarily mean change reduction - with the right attitudes and tools you can make frequent, fast, and well-controlled changes to software.

https://www.nginx.com/blog/microservices-at-netflix-architectural-best-practices/
Best Practices for Designing a Microservices Architecture
Create a Separate Data Store for Each Microservice
Keep Code at a Similar Level of Maturity
Do a Separate Build for Each Microservice

Deploy in Containers
Treat Servers as Stateless
https://www.nginx.com/blog/time-to-move-to-a-four-tier-application-architecture/

http://highscalability.com/blog/2015/12/1/deep-lessons-from-google-and-ebay-on-building-ecosystems-of.html
  • Large scale systems end up evolving into something that looks very similar: a set of polyglot microservices. Polyglot means microservices are can be written in more than one language.
At eBay and Google hundreds to thousands of independent services all work together.
  • Modern large scale systems compose services in a graph of relationships, not a hierarchy or set of tiers.
  • Services depend on many other services while being depended on by many services.
  • Older large scale systems were typically organized in strict tiers.
  • These best performing systems are more the product of evolution than intelligent design. At Google, for example, there never has been a centralized top down design of the system. It has evolved and grown over time in a very organic way.
  • Variation and natural selection. When a problem needs to be solved a new service is created, or more often extracted from an existing service or product. Services survive as long as they are used, as long as they provide value, otherwise they are deprecated.
  • These large scale systems develop from the bottom upClean design can be an emergent property rather than a product of top down design.
  • As an example consider some of the service layering for Google App Engine.
  • To encourage common practices and standardized conventions make it really easy to do the right thing and a lot harder to do the wrong thing.
  • Individual services are independent from one another.

Service Anti-Patterns

  • The Mega-Service
    • A service that does too much. What you want is an ecosystem of very small clean services.
    • A service that does too much is a just another monolith. It’s hard to reason about, it’s hard to scale, it’s hard to change, and it also creates more upstream and downstream dependencies than you want.
  • Shared Persistence
    • In the tiered model services are put in the application tier and the persistence layer is provided as a common service to the applications.
    • They did this at eBay and it didn’t work. It breaks the encapsulation of the service. Applications can back-door into your service by updating the database. It ends up reintroducing coupling of services. Shared databases don't allow for loosely coupled services.
    • Microservices prevent this problem by being small, isolated, and independent, which is how you keep your ecosystem healthy and growing.
http://yq.aliyun.com/articles/2764
和Microservice相对应的,这种方式一般被称为Monolithic(比较难传神的翻译)。所有的功能打包在一个WAR包里,基本没有外部依赖(除了容器),部署在一个JEE容器(Tomcat,JBoss,WebLogic)里,包含了DO/DAO,Service,UI等所有逻辑。
screenshot
Monolithic比较适合小项目,优点是:
  • 开发简单直接,集中式管理
  • 基本不会重复开发
  • 功能都在本地,没有分布式的管理开销和调用开销
它的缺点也非常明显,特别对于互联网公司来说(不一一列举了):
  • 开发效率低:所有的开发在一个项目改代码,递交代码相互等待,代码冲突不断
  • 代码维护难:代码功能耦合在一起,新人不知道何从下手
  • 部署不灵活:构建时间长,任何小修改必须重新构建整个项目,这个过程往往很长
  • 稳定性不高:一个微不足道的小问题,可以导致整个应用挂掉
  • 扩展性不够:无法满足高并发情况下的业务需求
所以,现在主流的设计一般会采用Microservice Architecture,就是基于微服务的架构。简单来说, 微服务的目的是有效的拆分应用,实现敏捷开发和部署 。
screenshot
用《The art of scalability》一书里提到的scale cube比较容易理解如何拆分。你看,我们叫分库分表,别人总结成了scale cube,这就是抽象的能力啊,把复杂的东西用最简单的概念解释和总结。X轴代表运行多个负载均衡器之后运行的实例,Y轴代表将应用进一步分解为微服务(分库),数据量大时,还可以用Z轴将服务按数据分区(分表)
screenshot

和Microservice相对应的,这种方式一般被称为Monolithic(比较难传神的翻译)。所有的功能打包在一个WAR包里,基本没有外部依赖(除了容器),部署在一个JEE容器(Tomcat,JBoss,WebLogic)里,包含了DO/DAO,Service,UI等所有逻辑。
screenshot
Monolithic比较适合小项目,优点是:
  • 开发简单直接,集中式管理
  • 基本不会重复开发
  • 功能都在本地,没有分布式的管理开销和调用开销
它的缺点也非常明显,特别对于互联网公司来说(不一一列举了):
  • 开发效率低:所有的开发在一个项目改代码,递交代码相互等待,代码冲突不断
  • 代码维护难:代码功能耦合在一起,新人不知道何从下手
  • 部署不灵活:构建时间长,任何小修改必须重新构建整个项目,这个过程往往很长
  • 稳定性不高:一个微不足道的小问题,可以导致整个应用挂掉
  • 扩展性不够:无法满足高并发情况下的业务需求
所以,现在主流的设计一般会采用Microservice Architecture,就是基于微服务的架构。简单来说, 微服务的目的是有效的拆分应用,实现敏捷开发和部署 。
screenshot
用《The art of scalability》一书里提到的scale cube比较容易理解如何拆分。你看,我们叫分库分表,别人总结成了scale cube,这就是抽象的能力啊,把复杂的东西用最简单的概念解释和总结。X轴代表运行多个负载均衡器之后运行的实例,Y轴代表将应用进一步分解为微服务(分库),数据量大时,还可以用Z轴将服务按数据分区(分表)
screenshot

The microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are **built around business capabilities** and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services , which may be written in different programming languages and use different data storage technologies.

1. 一些列的独立的服务共同组成系统
2. 单独部署,跑在自己的进程里
3. 每个服务为独立的业务开发
4. 分布式的管理
Martin自己也说了,每个人对微服务都可以有自己的理解,不过大概的标准还是有一些的。
  • 分布式服务组成的系统
  • 按照业务而不是技术来划分组织
  • 做有生命的产品而不是项目
  • Smart endpoints and dumb pipes(我的理解是强服务个体和弱通信)
  • 自动化运维(DevOps)
  • 容错
  • 快速演化

客户端如何访问这些服务?

所以,一般在后台N个服务和UI之间一般会一个代理或者叫API Gateway,他的作用包括
  • 提供统一服务入口,让微服务对前台透明
  • 聚合后台的服务,节省流量,提升性能
  • 提供安全,过滤,流控等API管理功能
我的理解其实这个API Gateway可以有很多广义的实现办法,可以是一个软硬一体的盒子,也可以是一个简单的MVC框架,甚至是一个Node.js的服务端。他们最重要的作用是为前台(通常是移动应用)提供后台服务的聚合,提供一个统一的服务出口,解除他们之间的耦合,不过API Gateway也有可能成为单点故障点或者性能的瓶颈。

服务之间如何通信?

因为所有的微服务都是独立的Java进程跑在独立的虚拟机上,所以服务间的通行就是IPC(inter process communication),已经有很多成熟的方案。现在基本最通用的有两种方式。这几种方式,展开来讲都可以写本书,而且大家一般都比较熟悉细节了,就不展开讲了。
  • 同步调用
    • REST(JAX-RS,Spring Boot)
    • RPC(Thrift, Dubbo, HSF)
  • 异步消息调用(Kafka, Notify, MetaQ)
而异步消息的方式在分布式系统中有特别广泛的应用,他既能减低调用服务之间的耦合,又能成为调用之间的缓冲,确保消息挤压不会冲垮被调用方,同时能保证调用方的服务体验,继续干自己该干的活,不至于被后台性能拖慢。不过需要付出的代价是一致性的减弱,需要接受数据最终一致性;还有就是后台服务一般要实现幂等性,因为消息发送出于性能的考虑一般会有重复;最后就是必须引入一个独立的broker,如果公司内部没有技术积累,对broker分布式管理也是一个很大的挑战。

这么多服务,怎么找?

在微服务架构中,一般每一个服务都是有多个拷贝,来做负载均衡。一个服务随时可能下线,也可能应对临时访问压力增加新的服务节点。服务之间如何相互感知?服务如何管理?这就是服务发现的问题了。一般有两类做法,也各有优缺点。基本都是通过zookeeper等类似技术做服务注册信息的分布式管理。当服务上线时,服务提供者将自己的服务信息注册到ZK(或类似框架),并通过心跳维持长链接,实时更新链接信息。服务调用者通过ZK寻址,根据可定制算法,找到一个服务,还可以将服务信息缓存在本地以提高性能。当服务下线时,ZK会发通知给服务客户端。
  • 客户端做:优点是架构简单,扩展灵活,只对服务注册器依赖。缺点是客户端要维护所有调用服务的地址,有技术难度,一般大公司都有成熟的内部框架支持,比如HSF。
  • 服务端做:优点是简单,所有服务对于前台调用方透明,一般在小公司在云服务上部署的应用采用的比较多。
screenshot

这么多服务,服务挂了怎么办?

  • 重试机制
  • 限流
  • 熔断机制
  • 负载均衡
  • 降级(本地缓存)
微服务的优点和缺点(或者说挑战)一样明显。
  • 优点
    • 开发简单
    • 技术栈灵活
    • 服务独立无依赖
    • 独立按需扩展
    • 可用性高
  • 缺点(挑战)
    • 多服务运维难度
    • 系统部署依赖
    • 服务间通信成本
    • 数据一致性
    • 系统集成测试
    • 重复工作
    • 性能监控

http://vanillajava.blogspot.com/2017/03/distributing-common-java-apis.html

Distributing data stores vs Private data stores in Microservices

Distributing data containers e.g. Maps, can be a way of avoiding having to think too much about distributing your application. Your business logic is much the same, and it is your data collections which are visible to all your services.
Using centralised or even distributed data stores have a number of scalability issues, as it requires every low level data access to be distributed in a generic way which isn’t optimised for particular business requirements.
Distributing business components with private data stores is the favoured approach of Microservices and it limits the "surface area" of each service which reduces security issues, performance considerations and gives you more freedom for independant changes to service’s data structures.
In this review, I will be focusing on distributed data containers, largely because the interfaces are available in the JDK and available for everyone to look at. I expect the conclusions drawn here are broadly similar for Business focused APIs, though each business component will vary.

Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts