Micro Service 技术体系

微服务技术体系介绍

  • 微服务技术

  • SpringBoot开发框架

  • Vertx异步框架

  • 容器技术和配套服务

  • 和原有JavaEE技术的对比和结合使用

微服务

  • 采用一组服务的方式来构建一个应用,服务独立部署在不同的进程中,不同服务通过一些轻量级交互机制来通信,例如 RPC、HTTP 等,服务可独立扩展伸缩,每个服务定义了明确的边界,不同的服务甚至可以采用不同的编程语言来实现,也可以使用不同的数据存储技术,由独立的团队来维护。

微服务组成图

ms1

单体式应用的不足

  • 随着时间推移逐渐变大

  • 敏捷开发和部署举步维艰

  • 启动速度长,开发和生产效率受到极大影响

  • 资源冲突时难以扩展

  • 整体可靠性脆弱

  • 不容易采用新的架构,技术或者编程语言

微服务扩展维度

func decomposition

微服务的优势

  • 更小,更简单的应用

    • 更容易理解和开发, 更快的构建和部署

    • 避免了jar/classpath hell

  • 更好的分布式协作:开发,部署,每个服务都可以扩展

  • 错误隔离

  • 避免了单一技术架构的风险

    • 整个系统的架构和服务层面的架构

    • 容易采用新技术

微服务的不足

  • 开发分布式系统的复杂性

    • 进程间通信

    • 需要处理局部失败问题

  • 需要处理涉及到多个数据库的事务

  • 测试分布式系统不易

  • 部署和运维分布式系统非常复杂

  • 需要管理涉及到多个服务的特性

互联网应用需要微服务

  • 海量用户和访问量

  • 需要成千上万的机器协同工作

  • 高效可靠的运维平台

  • 传统企业级架构无法满足

    • 单个机架,数量不多的集群服务能力

十二要素应用宣言(一)

  • 基准代码:一份代码,多份部署

  • 依赖:显式地声明依赖关系

  • 配置:在环境中存储配置信息,与语言和环境无关

  • 后端服务:当作附加资源可以部署时更换

  • 构建,发布,运行:发布时有唯一ID版本标示

  • 进程:以一个或者多个无状态的进程运行

十二要素应用宣言(二)

  • 端口绑定:通过端口提供服务,监听发送至该端口的请求

  • 并发:通过进程模型进行扩展

  • 易处理:快速启动和优雅终止保证健壮性

  • 开发环境和线上环境等价:尽可以的保持一致,缩小差异

  • 日志:把日志当作事件流直接输出到标准输出中

  • 管理进程:后台管理任务当作一次性进程运行

微服务总结

  • 通用语言 (Ubiquitous language)

  • 很好定义的模型和边界

  • 单一职责

  • 独立部署,可扩展和具有弹性

  • 通过异步消息进行通信

  • 拥有数据

  • 不会直接暴露公有API

SpringBoot

  • 快速构建基于Spring框架的独立进程应用

  • 通过Maven pom构建,组合多个starter

  • 自由选择各个层次的实现,比如web容器可以选用tomcat/undertow等

  • 利用SpringActuator提供产品上线监测的特性。

  • 注解定义的配置项和配置文件,Coc约定优于配置

SpringBoot 强大的集成能力

  • Tomcat, Jetty, undertow

  • WebMVC, Thymeleaf, Websocket

  • Spring Security

  • JPA, Spring Data, Mongo, Redis

  • JMS, RabbitMQ

  • Batch

配置项定义

  • @SpringBootApplication

  • @Configuration

  • @EnableAutoConfiguration

  • @ComponentScan

  • @EnableWebMvc

配置项文件

  • application.properties

  • yaml配置文件 application.yml

  • 按照profile定义:app-production.properties

  • classpath路径上

Starter POMs

  • 包含相关技术的starter pom, 以及很多社区的starter

  • 依赖定义,对应的配置项解析能力

  • 可能快速的构建应用和使其运行

  • 示例

    • spring-boot-starter-web

    • spring-boot-starter-data-rest

    • spring-boot-starter-security

    • spring-boot-starter-actuator

Spring Actuator

  • 可监视点

    • /health /metrics /trace

    • /info /dump /env

    • /dump /shutdown

  • JMX / SSH

  • Auditing 审计

  • Logging

SpringBoot Module 关系

springboot modules

Spring Cloud + Netflix OSS

  • Config Server

  • Eureka (Service Registry)

  • Ribbon (Load Balancer)

  • Hystrix (Circuit Breakers)

  • Zuul (Intelligent Routing)

SpringBoot Config Server

sb config server

Service Register (Eureka)

sb eureka

Hystrix

sb hystrix

Routing

sb zuul

Wildfly Swarm

  • 1.0.0.CR1

  • 基于Wildfly-core 2.1

  • JBoss MSC作为微内核核心

  • Fraction片段组装而成

  • 利用Maven的构建和打包能力

@ApplicationPath("/")
public class MyApplication extends Application {

    public MyApplication() {
    }
}
@Path("/")
public class EmployeeResource {
    @Inject PersistenceHelper helper;
    @GET @Produces("application/json")
    public Employee[] get() {
        return helper.getEntityManager().createNamedQuery("Employee.findAll",
          Employee.class).getResultList().toArray(new Employee[0]);
    }
}

性能对比

sb ws benchmark

Vert.x 3

  • 可以运行基于JVM多种语言的响应式编程开发工具

    • Java

    • Ruby

    • Javascript

  • 设计成可扩展和非阻塞的

  • 基于Netty网络库,类似NodeJs的设计思路

  • Json消息作为结构数据体

Reactor

  • Verticle异步模型

  • 内建的多线程支持

  • Event bus (消息通道,本地或者远程)

    • Point to point

    • Public/Subscribe

    • Request/Response

  • 微服务方式部署

线程模型

  • 传统的一个连接一个线程模式,如Tomcat

    • 工作线程阻塞,后来的线程必须等待

  • 一个线程处理所有请求,如NodeJs

    • 如果工作线程被阻塞,整个队列需要等待

    • 等待前面的工作完成(无法最好发挥多核优势)

  • 组合上述优点,对于长时间阻塞工作采用线程池

    • 多个EventLoop

并发

  • 组件是单线程模型

  • "Actor-style"并发方式

  • 和Java的并发模式不同

  • 无须使用synchronized, volatile, 加锁等

  • 告别线程竞争开发和调试大坑

支持的协议和数据表现形式

  • TCP/UDP - Client/Server

  • HTTP(s)/REST

  • WebSocket

  • RxJava

  • SockJS

Vert.x生态

  • 轻量级 Vert.x core核心

  • 扩展

    • Web

    • 数据访问 (JDBC, mongoDB, redis…​)

    • Security (Auth / JWT / OAuth2)

    • Reactive (RxJava)

  • Clustering (Hazelcast / JGroups)

Vert.x TCP Server

  public void start() throws Exception {
    vertx.createNetServer().connectHandler(sock -> {
      Pump.pump(sock, sock).start();
    }).listen(1234);
    System.out.println("Echo server is now listening");
  }

Vert.x HTTP Server

  public void start() throws Exception {
    vertx.createHttpServer().requestHandler(req -> {
      req.response().putHeader("content-type", "text/html").
      end("<html><body><h1>Hello from vert.x!</h1></body></html>");
    }).listen(8080);
  }

Vert.x Web Server

  public void start() throws Exception {
    Router router = Router.router(vertx);
    router.route().handler(routingContext -> {
      routingContext.response().putHeader("content-type", "text/html").end("Hello World!");
    });
    vertx.createHttpServer().requestHandler(router::accept).listen(8080);
  }

RxJava 数据获取方式

rxjava data access

API

Observer<HttpServer> observer = new Observer<HttpServer>() {
  @Override public void onNext(HttpServer o) {
  }
  @Override public void onError(Throwable e) {
  }
  @Override public void onCompleted() {
  }
};
Handler<AsyncResult<HttpServer>> handler = RxHelper.toFuture(observer);

HTTP Client request

HttpClient client = vertx.createHttpClient(new HttpClientOptions());
HttpClientRequest request = client.request(HttpMethod.GET, 8080, "localhost", "/the_uri");
request.toObservable().subscribe(
    response -> {
      // Process the response
    },
    error -> {
      // Could not connect
    }
);
request.end();

Container 容器

  • 看作是轻量级VM

  • 拥有自己的进程空间

  • 拥有自己的网络接口

  • 以root身份运行

  • 和主机共享内核

Docker

  • 以docker容器为资源分割和调度的基本单位

  • 封装整个软件运行环境

  • 为开发者和系统管理员设计的

  • 用于构建,发布和运行分布式应用的平台

命名空间隔离

  • pid 进程编号

  • uts 主机名与域名

  • ipc 信号量,消息队列和共享缓存

  • network 网络设备,网络站,端口等

  • mount 挂载点

  • user 用户和用户组

VM vs Container

container vs vm

Docker带来的好处

  • 持续部署和测试

  • 跨云平台支持

  • 环境标准化和版本控制

  • 高资源利用率和隔离

  • 容器跨平台性与镜像

  • 应用镜像仓库,方便易用

镜像分层文件系统

  • Copy-on-write 写时复制机制

  • 堆叠式

    • union 联合文件系统 AUFS, overlayfs

    • snapshot 快照文件系统 BTRFS, ZFS

    • copy-on-write 块设备 Device-mapper

Docker 文件系统比较

docker fs

Docker Volumn 数据卷

  • 存在于多个容器上的文件或者文件夹

  • 不同容器之间共享和重用

  • 对数据卷的操作会马上生效

  • 不会影响到镜像本身

  • 类似mount操作

Docker镜像

  • 含有启动Docker容器所需文件系统结构内容

  • 按照一定层次结构叠加而成

  • 存放在registry仓库中

  • 公有仓库Docker Hub (hub.docker.com)

  • repository名称 username/repo_name

镜像操作

  • 登录账户

  • 使用镜像 pull拉取操作

  • commit,提交变更的部分

  • build,完成一个新镜像的构建

  • push,制作镜像并上传至仓库

Docker网络

  • docker0网桥

    • veth pair连接各个容器网络

    • 通过网桥转发到eth0网卡上

  • 可以使用brctl查看和管理网桥

  • 添加一些iptables规则

  • 四种网络模式:bridge, host, container, none

  • 容器间可以使用 --link通信

Kubernetes

  • 一个管理docker容器的平台

  • 高级特性

    • 容器分组

    • 负载均衡

    • 自动扩展,应用弹性伸缩

  • 源于Google实践项目

核心概念(1)

  • Pod 一组容器

  • Label 标签用于标记pod

  • Replication controller 副本控制器

  • Service 提供相同服务的Pod

  • etcd 元数据服务

核心概念(2)

  • Kubelet 节点上的代理,负责Pod的创建,修改,监控,删除等

  • Proxy pod负载均衡代理

  • cAdvisor 资源监控和性能分析

  • Scheduler 集群中的调度齐,调度分配pod到工作节点

  • Controller Manager 集群内部的管理控制中心

  • API server 提供了资源对象的操作入口

kubernetes architecture

Pod

  • 若干个docker容器构成的容器组

  • 创建,调度,管理的最小单元

  • pod里的容器共享网络和存储

  • pid/ipc/uts namespace也共享

  • 方便传统应用的部署

Replication controller

  • 决定pod同时运行多少个副本

  • 通过预先定义的pod模板来创建pod

  • 对pod的数量和健康状况通过副本选择器进行监控

  • 使用场景

    • 弹性伸缩,修改副本数

    • 滚动更新,灰度发布

    • 应用的多版本release跟踪

Service

  • 看作一组提供相同服务的pod对外访问接口

  • 代理来确保IP地址固定

  • 为多个pod做负载均衡,路由策略(默认轮转)

  • 建立iptables规则

  • 通过DNS服务的发现形式

Nginx作为反向代理和应用路由

  • 负载均衡

  • 健康检查

  • 请求路由

  • 请求响应重写

  • 缓存

  • 压缩

  • SSL处理

Nginx的特性

  • 负载均衡策略

    • round-robin 轮询

    • IP hash 根据IP地址的hash值来分布负载

    • 最小连接方法

  • 失败检测

  • 会话持久性

Nginx对协议的支持

  • TCP负载均衡

  • HTTP keepalive连接

  • HTTP SSL

  • HTTP/2

  • Websocket

几种均衡负载的组合使用

  • Docker和Kubernetes

    • 利用操作系统层,网桥和iptables等

  • 入口点反向代理

    • Nginx分发 (Undertow采用相同的设计思路)

    • apache modules成熟也足够强大

  • 应用层的负载均衡和路由

    • Netflix Ribbon/Zuul

  • 根据应用需要和架构需求,搭配使用

API Gateway

  • Routing 路由

  • Service aggregation 服务聚合

  • Security (Encryption,Signing) 加密签名等

  • Protocol conversion 协议转换

  • Legacy adapters 适配器

  • Payload transformation 报文格式变换

  • Service catalog 服务目录

微服务安全

  • 对外API暴露需要安全防护

  • 认证 (密码,token,指纹,二次验证)

  • 授权 (三方服务)

  • 加解密,不被篡改

  • 审计 (记录每一步操作)

  • 统一管理

安全标准和实现方式

  • LDAP/Kerberos

  • SAML

  • OAuth2

  • Social Login (Github, Twitter)

  • KeyCloak - SSO server中心管理点

  • 和应用服务器集成

分布式跟踪系统

  • 微服务分布式,需要有工具来检测依赖性以及性能

  • 后台处理流程,收发消息等用图示方式显示

  • 跟踪信息的元数据:trace, span, log(annotation)

  • AOP 实现思路,埋点,javaagent

  • Zipkin开源项目

zipkin screenshot

应用监测和管理

  • 代码事务执行效率分析

  • 错误率,每分钟请求数

  • 服务器监控

  • 报警和报告

  • 可视化呈现

newrelic summary2

ELK统一管理日志

  • Elasticsearch 搜索平台,也是一个分布式文档数据库

    • 配置成集群方式

    • 多个节点的分布式系统

    • 分片和副本

  • Logstash 日志的收集和分析

    • agent用来监控和过滤收集日志

  • Kibana 日志分析提供友好的web界面

服务治理的需求(1)

  • 服务注册和发现

  • 软负载均衡和容错

  • 服务监控和统计

  • 容量评估和流量控制

  • 上线审批和下线通知

  • 服务路由

  • 服务编排

服务治理的需求(2)

  • 协作流程

  • 服务黑白名单

  • 服务依赖关系

  • 权限控制,角色授权

  • 服务分层架构

  • 调用链跟踪

  • 故障导流和隔离

  • 自动部署

服务治理的需求(3)

  • 服务降级

  • 优先级调度

  • 自动测试

  • 服务超时控制

  • 服务降级,权重动态调整

  • 多版本管理

  • 容器和资源调度

  • 健康度状态检测

Corba时代的微服务

  • 2000年左右,C/C++编写的Corba程序

  • 每个服务一个独立进程

  • IDL定义接口,生成框架代码并编译成可执行程序

  • 命名服务,集群和容错

  • 消息,事务,安全

  • 历史重演

JavaEE应用服务器

  • 基于Web容器,部署应用

  • 是否需要分布和组件的线程安全性,选择EJB还是CDI

  • JavaEE7非常完备和庞大,33个子规范

  • 适用于企业级应用开发,应用对事务性有较高的需求

  • 一键式的部署和方便管理运维

事务的需求

  • 对数字敏感度高的应用,事务要求也高

    • 财务软件

    • 企业业务系统

    • 保持一致性

  • 访问量不是很大,安全性要求高

  • 最终一致性适用的场景

    • 跨越企业组织需要优化业务流程

    • 技术上采用异步消息等机制

EJB的优势

  • 线程安全

  • 对象池

  • 远程访问

    • RMI/IIOP

    • Web Services

  • MDB/JMS

  • Timer/Scheduled events

  • 安全集成

远程EJB

  • Java分布式调用

  • 同步/异步方法都可以支持

  • 选择合适的数据传输粒度

  • MDB配合消息使用

  • 应用服务器实现支持集群/容错等高级特性

其他RPC

  • SpringRemoting

    • HttpInvoker

    • Hessian

  • Dubbo

  • Thrift

  • gRPC

JavaEE中的异步改进

reactivejavaee

消息机制运用

  • 消息是解耦的主要设计方式

  • 分布式消息

    • 按协议传输内容

    • 实现事务最终一致性

    • 编程语义和本地做到统一,如RxJava

  • 进程内的通知机制

    • Event/Listener

    • 异步响应式编程,不方便单步调试,但整体效率高

Spring框架和CDI规范

  • 是相似的设计方案

  • Spring框架在于实现具体化

  • CDI在于API和设计思路的统一

  • CDI非常强大,有Apache DeltaSpike外延项目

  • DDD设计,每个大型应用应当有自定义的CDI组件

JPA和SpringData

  • Hibernate是ORM的经典成功项目

  • JPA API总结了通用的实体和关系数据库之间的映射

  • 需要对NoSQL/NewSQL有支持

  • SpringData高效简洁的对主流数据库支持

  • 其他可以选择方案Hibernete OGM / JDO

    • 解析到数据结构,而不是实体对象类中

分布式的数据源

  • 分布式数据库

  • 分布式缓存

  • 分布式的文件系统

  • 支持分库分表,按照维度分片

  • 设计时需要仔细衡量事务的重要性

“微”服务?

  • 打包后的SpringBoot应用20M以上

  • NodeJs的应用各种依赖也很多

  • "微"不是体积上的微小,而是限制在领域边界内

  • 各层都需要打包到应用中,或者在环境路径中

    • 服务层,数据层,表现层都得有

    • 服务自理,具有安全,管理性,日志等方方面面的内容

    • 所有的微服务体积总和远大于单一的应用服务器加上部署包

界面技术选用

  • 应用逻辑中状态信息保存的位置 - Http/Json

  • Native界面:MFC/.NET/Cocoa

  • 经典的MVC模板:JSP/SpringMVC/Freemaker等

  • Ios/Android原生界面

  • JavaSwing/EclipseSWT

  • JQuery/Bootstrap - AngularJS - ReactNative

  • JSF - GWT- JavaFX

是否使用微服务体系架构

  • 针对不同的应用和系统规模

  • 强事务的要求

  • 用户量和并发访问量

  • 用户访问界面类型

  • 运维团队的规模和技术能力

  • 架构师和开发者的系统思维

应用部署总是部署到容器中

  • 容器是运行应用的环境,需要被管理有所限制

    • Docker是操作系统级别的容器

    • JVM中的容器(多租户能力的支持)

  • 应用服务器的分布扩展,就变成了微服务治理体系

    • 进程内和跨进程通信

    • 分布式通信

  • 需求没变,如安全,监控,日志等,分布式统一管理

说明

  • 参考了借鉴了以下公司的公开资料

    • Nginx

    • Netflix

    • Redhat

    • Pivotal

    • Lightbend

Thanks!