说说如何设计一个良好的 API
版本号在 RESTful API 中,API 接口应该尽量兼容之前的版本。但是,在实际业务开发场景中,可能随着业务需求的不断迭代,现有的 API 接口无法支持旧版本的适配,此时如果强制升级服务端的 API 接口将导致客户端旧有功能出现故障。实际上,Web 端是部署在服务器,因此它可以很容易为了适配服务端的新的 API 接口进行版本升级,然而像 Android 端、IOS 端、PC 端等其他客户端是运行在用户的机器上,因此当前产品很难做到适配新的服务端的 API 接口,从而出现功能故障,这种情况下,用户必须升级产品到最新的版本才能正常使用。 为了解决这个版本不兼容问题,在设计 RESTful API 的一种实用的做法是使用版本号。一般情况下,我们会在 url 中保留版本号,并同时兼容多个版本。 【GET】 /v1/users/{user_id} // 版本 v1 的查询用户列表的 API 接口【GET】 /v2/users/{user_id} // 版本 v2 的查询用户列表的 API 接口 现在,我们可以不改变版本 v1 的查询用...
你怎么理解 RESTful
2000 年,Roy Thomas Fielding 博士在他那篇著名的博士论文《Architectural Styles and the Design of Network-based Software Architectures》中提出了几种软件应用的架构风格,REST 作为其中的一种架构风格在这篇论文的第5章中进行了概括性的介绍。 REST 是”REpresentational State Transfer”的缩写,可以翻译成”表现状态转换”,但是在绝大多数场合中我们只说 REST 或者 RESTful。Fielding 在论文中将 REST 定位为”分布式超媒体应用(Distributed Hypermedia System)”的架构风格,它在文中提到一个名为”HATEOAS(Hypermedia as the engine of application state)”的概念。 我们利用一个面向最终用户的 Web 应用来对这个概念进行简单阐述:这里所谓的应用状态(Application State)表示 Web 应用的客户端的状态,简单起见可以理解为会话状态。资源在浏览器...
说说 Dubbo 的实现原理
Dubbo 作为 RPC 框架,实现的效果就是调用远程的方法就像在本地调用一样。如何做到呢? 本地有对远程方法的描述,包括方法名、参数、返回值,在 Dubbo 中是远程和本地使用同样的接口 要有对网络通信的封装,要对调用方来说通信细节是完全不可见的,网络通信要做的就是将调用方法的属性通过一定的协议(简单来说就是消息格式)传递到服务端 服务端按照协议解析出调用的信息;执行相应的方法;在将方法的返回值通过协议传递给客户端;客户端再解析;在调用方式上又可以分为同步调用和异步调用; 三条是 RPC 的通用骨架,Dubbo 的独特之处在于它的微内核+SPI 扩展架构与全链路治理设计。本文按”架构形态 → 调用链对象流 → 注册中心交互 → SPI 机制”四层展开。 架构形态:微内核 + SPIDubbo 内核只做流程编排(Protocol/Cluster/Registry 等接口),全部能力以 SPI 扩展点插入: 协议:dubbo / triple / rest / grpc 注册中心:zookeeper / nacos ...
说说 RPC 的实现原理
首先需要有处理网络连接通讯的模块,负责连接建立、管理和消息的传输。其次需要有编解码的模块,因为网络通讯都是传输的字节码,需要将我们使用的对象序列化和反序列化。剩下的就是客户端和服务器端的部分,服务器端暴露要开放的服务接口,客户调用服务接口的一个代理实现,这个代理实现负责收集数据、编码并传输给服务器然后等待结果返回。 这段描述勾勒出 RPC 的四大件:网络通讯、编解码、服务端暴露、客户端代理。本文把它们串成一次完整调用,并补上生产环境绕不开的两块:服务发现与负载均衡。 RPC 解决什么问题微服务拆开后,订单服务要调用户服务,两者在不同进程甚至不同机器。直接写 Socket 代码意味着每个调用点都要处理连接、字节拼装、超时重试——重复且易错。RPC 的目标是:让远程调用看起来像本地方法调用,把网络细节全部藏进框架层。 一次调用的完整链路客户端侧: 动态代理:调用方持有服务接口的代理对象,方法调用被拦截 封装请求:接口名、方法名、参数类型、参数值打包成 Request 对象 序列化:Request → 字节流(Hessian/Protobuf/Kryo,选型权衡可...
你怎么理解 RPC 框架
什么是 RPC?RPC 是指远程过程调用,也就是说两台服务器 A,B 一个应用部署在 A 服务器上,想要调用 B 服务器上应用提供的函数或方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。 RPC 是如何通讯的? 要解决通讯的问题,主要是通过在客户端和服务器之间建立 TCP 连接,远程过程调用的所有交换的数据都在这个连接里传输。连接可以是按需连接,调用结束后就断掉,也可以是长连接,多个远程过程调用共享同一个连接。 要解决寻址的问题,也就是说,A 服务器上的应用怎么告诉底层的 RPC 框架,如何连接到 B 服务器(如主机或 IP 地址)以及特定的端口,方法的名称是什么,这样才能完成调用。比如基于 Web 服务协议栈的 RPC,就要提供一个 endpoint URI,或者是从 UDDI 服务上查找。如果是 RMI 调用的话,还需要一个 RMI Registry 来注册服务的地址。 当 A 服务器上的应用发起远程过程调用时,方法的参数需要通过底层的网络协议如 TCP 传递到 B 服务器,由于网络协议是基于二进制的,内存中的参数的值要序列化成二进制的...
如何解决跨域
什么是跨域问题?跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对 JavaScript 施加的安全限制。 什么是同源?所谓同源是指,域名,协议,端口均相同 http://www.funtl.com --> http://admin.funtl.com 跨域 http://www.funtl.com --> http://www.funtl.com 非跨域 http://www.funtl.com --> http://www.funtl.com:8080 跨域 http://www.funtl.com --> https://www.funtl.com 跨域 使用 CORS(跨资源共享)解决跨域问题CORS 是一个 W3C 标准,全称是”跨域资源共享”(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制。 CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器不能低于 IE1...
微服务哪些框架
Dubbo是阿里巴巴服务化治理的核心框架,并被广泛应用于阿里巴巴集团的各成员站点。阿里巴巴近几年对开源社区的贡献不论在国内还是国外都是引人注目的,比如 JStorm 捐赠给 Apache 并加入 Apache 基金会等,为中国互联网人争足了面子,使得阿里巴巴在国人眼里已经从电商升级为一家科技公司了。 Spring Cloud从命名我们就可以知道,它是 Spring Source 的产物,Spring 社区的强大背书可以说是 Java 企业界最有影响力的组织了,除了 Spring Source 之外,还有 Pivotal 和 Netflix 是其强大的后盾与技术输出。其中 Netflix 开源的整套微服务架构套件是 Spring Cloud 的核心。 两大框架的介绍需要更新到今天的格局:Netflix 组件已停止维护、Spring Cloud 完成代际替换、Dubbo 与 Spring Cloud 出现融合趋势、云原生(Service Mesh/K8s)成为第三极。本文按”治理套件 vs RPC 框架 vs 云原生”三层重画地图,并给出选型依据。 第一层:Spring C...
前后端分离是如何做的
在前后端分离架构中,后端只需要负责按照约定的数据格式向前端提供可调用的 API 服务即可。前后端之间通过 HTTP 请求进行交互,前端获取到数据后,进行页面的组装和渲染,最终返回给浏览器。 一句话定义之外,”如何做”要落到五个工程面:契约怎么定、跨域怎么通、认证怎么带、部署怎么分、协作怎么管。本文按这五面给出可执行的分离方案。 契约先行:API 是前后端唯一的交界 接口文档即合同:OpenAPI/Swagger 或 YApi/Apifox 维护接口定义(路径、方法、入参、出参、错误码),变更走评审流程,杜绝”口头改接口” 统一响应 envelope:{ code, message, data, traceId },业务错误用 code 表达而非 HTTP 状态码混用(或明确约定:HTTP 表传输层、code 表业务层) 版本化:URL 前缀 /v1/ 或 Header 版本;破坏性变更升版本、旧版本限期下线 Mock 先行:契约定稿后前端用 Mock 平台并行开发,不被后端进度阻塞——这是分离带来的最大效率收益 跨域:...
集群与负载均衡的算法与实现
负载均衡什么是负载均衡呢?用户输入的流量通过负载均衡器按照某种负载均衡算法把流量均匀的分散到后端的多个服务器上,接收到请求的服务器可以独立的响应请求,达到负载分担的目的。从应用场景上来说,常见的负载均衡模型有全局负载均衡和集群内负载均衡,从产品形态角度来说,又可以分为硬件负载均衡和软件负载均衡。全局负载均衡一般通过DNS实现,通过将一个域名解析到不同VIP,来实现不同的region调度能力;硬件负载均衡器常见的有F5、A10、Array,它们的优缺点都比较明显,优点是功能强大,有专门的售后服务团队,性能比较好,缺点是缺少定制的灵活性,维护成本较高;现在的互联网更多的思路是通过软件负载均衡来实现,这样可以满足各种定制化需求,常见的软件负载均衡有 LVS、Nginx、Haproxy。 阿里云高性能负载均衡使用 LVS 和 Tengine,我们在一个 region 区分不同的机房,每个机房都有 LVS 集群和 Tengine 集群,对于用户配置的四层监听,LVS 后面会直接挂载用户 ECS,七层用户监听 ECS 则挂载在 Tengine 上,四层监听的流量直接由 LVS 转发到 EC...
分布式事务
分布式一致性在分布式系统中,为了保证数据的高可用,通常,我们会将数据保留多个副本(replica),这些副本会放置在不同的物理的机器上。为了对用户提供正确的 CRUD 等语义,我们需要保证这些放置在不同物理机器上的副本是一致的。 为了解决这种分布式一致性问题,前人在性能和数据一致性的反反复复权衡过程中总结了许多典型的协议和算法。其中比较著名的有二阶提交协议(Two Phase Commitment Protocol)、三阶提交协议(Three Phase Commitment Protocol) 和 Paxos 算法。 分布式事务 分布式事务是指会涉及到操作多个数据库的事务。其实就是将对同一库事务的概念扩大到了对多个库的事务。目的是为了保证分布式系统中的数据一致性。分布式事务处理的关键是必须有一种方法可以知道事务在任何地方所做的所有动作,提交或回滚事务的决定必须产生统一的结果(全部提交或全部回滚) 在分布式系统中,各个节点之间在物理上相互独立,通过网络进行沟通和协调。由于存在事务机制,可以保证每个独立节点上的数据操作可以满足 ACID。但是,相互独立的节点之间无法准确的知道其他...















