1、背景java
最初遇到这个问题是去58面试。部门领导是原同事,因此面试比较水。水到什么程度呢?mysql
面试就是走个形式而已,不会不过的。linux
一面面试官就问了一个问题:“一个请求过来都通过了什么?” 剩下的全是闲聊。顺便展现一下公司和部门的优点。期待加入的意思。面试
声明sql
面试如此之松是基于两点:数据库
第一点,与原同事多年的共事已经展现了能力和综合素质,比几个小时的面试获得的结论靠谱的多。缓存
第二点,原同事自己认人识人的能力获得了其余人的承认,因此你们放心他推荐的人。服务器
毕竟没人愿意让一个不合适的人加入本身团队拉低总体水准。网络
2、问题考察点多线程
深度和广度的综合考察
3、静儿的答案
创建虚拟场景
☆ 项目
容器调度服务(根据用户传入的机房、CPU、内存等信息给用户建立所须要的机器)。
项目所用技术栈:SpringBoot、Thrift、缓存、mysql、k8s
☆ 需求
程序中须要用thrift(RPC调用)请求基础服务取全部的机房信息。
☆ 设计
基础服务提供了「傻瓜式」客户端给调用方。客户端只须要引入jar包,就能够像调用本地接口同样进行访问。
客户端实现方法
由于机房信息是低频的、对变动必定时延不敏感的资源信息。因此客户端首先RPC去远程取结果放到本地JVM缓存中。每次调用直接返回JVM缓存信息。客户端有定时任务定时将最新结果刷新到JVM缓存。
设计特色:
一、对thrift接口作封装,封装包括设定了远程获取异常的重试次数、重试间隔、远程服务信息等。缘由:基础服务提供方本身最清楚本身服务的响应时间、服务可用性等信息,本身设置更为精确,避免对使用方形成困扰。
二、每次返回本地JVM存的机房信息。信息更新经过自带定时任务。缘由:基础服务提供方本身最清楚本身的资源被更新频率如何,提供数据的实时性重要性如何。怎么保持数据一致性。怎样更高效。这些难题不该该抛给调用方。
三、懒加载处理。缘由:不能由于jar包被引用就直接占用内存、CPU等资源。要按需提供。
服务端实现方法
服务端收到请求,考虑到这个是基础服务,使用方多。为了防止压力直接做用于数据库,上面加了一层集中式缓存。不穿透的状况下,直接返回缓存信息。
数据库中的全部机房信息是从k8s标签中获取过滤的。有变化直接刷缓存。即数据库中存的是全部的标签信息,其中一个小功能是从全部标签中过滤机房标签。这种设计是区别于有个机房管理系统录入这种管理,机房信息永远是实时准确的。(这块涉及到内部系统的设计问题,若是看不懂直接忽略便可。)
☆ 请求过来通过了什么
从程序设计上,大致通过的如上图。限于篇幅(若是你想了解不限于篇幅是个什么状态,能够阅读下面一篇《一个请求过来都通过了什么?(2017年http版)》),本篇不讲JVM通过了怎样的过程,主内存和工做内存交互,内存可能的分页,numa绑核、定频非定频等等。深度上只介绍thrift调用这一层。
笼统的过程如上图。大致分为三个部分:
一、有IP直接访问IP,没有IP经过其余信息获取到IP。
在此部分中,第一次链接须要根据环境和服务标识获取机器列表。客户端通常会有本地进程代理。对于美团OCTO来讲,就是Sg_Agent(服务治理代理)。代理会和OCTO服务器进行通讯,及时获取最新信息。链接创建后,下次访问就是直接IP访问了。
二、经过IP访问服务端,根据类名+方法签名获取方法。
三、经过拦截器认证的请求被服务端处理后返回结果。
Thrift内部的架构是分层次的。客户端和服务端均可大致分为代码层、协议层、传输层、IO处理层四部分。客户端和服务端的IO处理层直接交互。
代码层:
代码在美团OCTO体系中MtThrift中会直接由框架自动从java代码转成IDL文件,框架再根据IDL文件生成代码实现数据的读写。
协议层(实现Tprotocol接口):
将数据编码、解码。最三种的三种传输格式支持是:二进制格式、压缩格式、Json格式。
传输层(实现Ttransport接口):
提供从网络等媒介读取和写入数据的方式。经常使用的有:向文件进行读写、从内存上读写、压缩读写。
IO处理层:
这层所作的就是阻塞、非阻塞,单线程、多线程这些。通常像获取全部机房信息这样的读操做用的是多线程阻塞方式。写操做通常用多线程非阻塞方式。
再往下linux系统层的东西也是能够讲讲的,内容有点多,你们本身作思考题吧。还有涉及网络传输的信道、全双工传输模式这些,你们能够本身想想,查一查。
4、总结
本次公众号文章共三篇《一个请求过来都通过了什么?(Thrift版)》、《一个请求过来都通过了什么?(2017年http版)》、《思惟发散的双刃剑》。首篇是刚写的,第二篇是17年写的。最后一篇是一些总结思考。