共计 12258 个字符,预计需要花费 31 分钟才能阅读完成。
前言
文本已收录至我的 GitHub 仓库,欢送 Star:https://github.com/bin3923282…
种一棵树最好的工夫是十年前,其次是当初
Tips
面试指南系列,很多状况下不会去深挖细节,是小六六以被面试者的角色去回顾常识的一种形式,所以我默认大部分的货色,作为面试官的你,必定是懂的。
https://www.processon.com/vie…
下面的是脑图地址
叨絮
分布式系统开发,微服务架构的一种支流实现形式,当然在面试中是必不可少的拉。
而后上面是后面的文章汇总
- 2021-Java 后端工程师面试指南 -(引言)
- 2021-Java 后端工程师面试指南 -(Java 根底篇)
- 2021-Java 后端工程师面试指南 -(并发 - 多线程)
- 2021-Java 后端工程师面试指南 -(JVM)
- 2021-Java 后端工程师面试指南 -(MySQL)
- 2021-Java 后端工程师面试指南 -(Redis)
- 2021-Java 后端工程师面试指南 -(Elasticsearch)
- 2021-Java 后端工程师面试指南 -(音讯队列)
- 2021-Java 后端工程师面试指南 -(SSM)
什么是 SpringBoot 呢
简而言之,从实质上来说,Spring Boot 就是 Spring,它做了那些没有它你本人也会去做的 Spring Bean 配置。基于约定大于配置的一个实践
说说 SpringBoot 的特点吧
- 开发基于 Spring 的应用程序很容易。
- Spring Boot 我的项目所需的开发或工程工夫显著缩小,通常会进步整体生产力。
- Spring Boot 不须要编写大量样板代码、XML 配置和正文。
- Spring 疏导应用程序能够很容易地与 Spring 生态系统集成,如 Spring JDBC、Spring ORM、Spring Data、Spring Security 等。
- Spring Boot 遵循“回心转意的默认配置”,以缩小开发工作(默认配置能够批改)。
- Spring Boot 应用程序提供嵌入式 HTTP 服务器,如 Tomcat 和 Jetty,能够轻松地开发和测试 web 应用程序。(这点很赞!一般运行 Java 程序的形式就能运行基于 Spring Boot web 我的项目,省事很多)
说说 @SpringBootApplication 这个注解吧
能够看出大略能够把 @SpringBootApplication 看作是 @Configuration、@EnableAutoConfiguration、@ComponentScan 注解的汇合。依据 SpringBoot 官网,这三个注解的作用别离是:
- @EnableAutoConfiguration:启用 SpringBoot 的主动配置机制
- @ComponentScan:扫描被 @Component (@Service,@Controller)注解的 bean,注解默认会扫描该类所在的包下所有的类。
- @Configuration:容许在上下文中注册额定的 bean 或导入其余配置类。
- 所以说 @SpringBootApplication 就是几个重要的注解的组合,为什么要有它?当然是为了省事,防止了咱们每次开发 Spring Boot 我的项目都要写一些必备的注解。这一点在咱们平时开发中也 常常用到,比方咱们通常会提一个测试基类,这个基类蕴含了咱们写测试所须要的一些根本的注解和一些依赖。
晓得 SpringBoot 的钩子函数吗,如何对你我的项目的启动和死亡做监控。
- 启动的时候,比方 CommandLineRunner 重写它的 run 办法,就能在启动的时候做一个钩子函数,比方链接钉钉等
- 意外宕机也是能够的,@PreDestroy 这个注解也能实现,在宕机之前回调这个办法,实现钉钉机器人等。
理解 spring boot 中的 spring factories 机制吗?
Spring Factories. 这种机制实际上是仿照 java 中的 SPI 扩大机制实现的。
spring -core 包里定义了 SpringFactoriesLoader 类,这个类实现了检索 META-INF/spring.factories 文件,并获取指定接口的配置的性能。在这个类中定义了两个对外的办法:
-loadFactories 依据接口类获取其实现类的实例,这个办法返回的是对象列表
- loadFactoryNames 依据接口获取其接口类的名称,这个办法返回的是类名的列表。
说说 springBoot 的主动配置原理吧
首先咱们晓得 SpringBoot 我的项目的启动注解 @SpringBootApplication 中有一个 @EnableAutoConfiguration,这个就是开启 springBoot 的主动注册机制
能够看到,在 @EnableAutoConfiguration 注解内应用到了 @import 注解来实现导入配置的性能,而 EnableAutoConfigurationImportSelector 外部则是应用了 SpringFactoriesLoader.loadFactoryNames 办法进行扫描具备 META-INF/spring.factories 文件的 jar 包
最初再加上咱们的 EnableAutoConfiguration 读取咱们在配置文件中的文件就能够实现主动配置了,就比方咱们的 springboot Admin, 咱们的 client 只有配置下配置文件就能胜利了,起因就是这个
下面这些都是 Spring Boot 中的主动配置相干类;在启动过程中会解析对应类配置信息。每个 Configuation 类都定义了相干 bean 的实例化配置。都阐明了哪些 bean 能够被主动配置,什么条件下能够主动配置,并把这些 bean 实例化进去。如果咱们自定义了一个 starter 的话,也要在该 starter 的 jar 包中提供 spring.factories 文件,并且为其配置 org.springframework.boot.autoconfigure.EnableAutoConfiguration 对应的配置类。所有框架的主动配置流程根本都是一样的,判断是否引入框架,获取配置参数,依据配置参数初始化框架相应组件
说说 SpringBoot 的启动流程吧
其实这块很大一部分和 spring 的启动流程有重叠的,然而,咱们还是从头到尾来过一遍,当温习了。
SpringBoot 的启动次要是通过实例化 SpringApplication 来启动的,启动过程次要做了以下几件事件:配置属性、获取监听器,公布利用开始启动事件初、始化输出参数、配置环境,输入 banner、创立上下文、预处理上下文、刷新上下文(加载 tomcat 容器)、再刷新上下文、公布利用曾经启动事件、公布利用启动实现事件。
实例化 SpringApplication 时做了什么
- 推断 WebApplicationType,次要思维就是在以后的 classpath 下搜寻特定的类
- 搜寻 META-INF\spring.factories 文件配置的 ApplicationContextInitializer 的实现类
- 搜寻 META-INF\spring.factories 文件配置的 ApplicationListenerr 的实现类
- 推断 MainApplication 的 Class
SpringApplication 的 run 办法做了什么?
- 创立一个 StopWatch 并执行 start 办法,这个类次要记录工作的执行工夫
- 配置 Headless 属性,Headless 模式是在短少显示屏、键盘或者鼠标时候的系统配置
- 在文件 META-INF\spring.factories 中获取 SpringApplicationRunListener 接口的实现类 EventPublishingRunListener,次要公布 SpringApplicationEvent
- 把输出参数转成 DefaultApplicationArguments 类
- 创立 Environment 并设置比方环境信息,零碎相熟,输出参数和 profile 信息
- 打印 Banner 信息
- 创立 Application 的上下文,依据 WebApplicationTyp 来创立 Context 类,如果非 web 我的项目则创立 AnnotationConfigApplicationContext,在构造方法中初始化 AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner
- 在文件 META-INF\spring.factories 中获取 SpringBootExceptionReporter 接口的实现类 FailureAnalyzers
- 筹备 application 的上下文
- 初始化 ApplicationContextInitializer
- 执行 Initializer 的 contextPrepared 办法,公布 ApplicationContextInitializedEvent 事件
- 如果提早加载,在上下文增加处理器 LazyInitializationBeanFactoryPostProcessor
- 执行加载办法,BeanDefinitionLoader.load 办法,次要初始化了 AnnotatedGenericBeanDefinition
- 执行 Initializer 的 contextLoaded 办法,公布 ApplicationContextInitializedEvent 事件
- 刷新上下文(后文会独自剖析 refresh 办法),在这里真正加载 bean 到容器中。如果是 web 容器,会在 onRefresh 办法中创立一个 Server 并启动。
refresh 办法 和 spring 的有点不同
srping 中的 onrefesh 办法是空的,这个外面是须要去加载 web 容器的如 tomcat jetty 等,具体的办法还是一样的,这边就不说了,能够去看 ssm 那篇
说说 SpringCloud 容器和 SpringBoot 容器的关系呗
首先说一点就是 如果是 SpringBoot 呢?他是能够独自应用的,而 SpringCloud 是不能独自应用的,它必须依赖 SpringBoot。
在咱们 SpringCloud 的我的项目中呢,整个我的项目的容器分为三层
- BootStrap Spring 容器:由 SpringCloud 监听器创立,用来初始化 SpringCloud 上下文
- SpringBoot Spring 容器:由 SpringBoot 创立,也是我的项目中罕用的 Spring 容器。
- 微服务 Spring 相干容器:Feign 和 Ribbon 配置类对应的上下文,由配置容器形象工厂 NamedContextFactory 创立,用于容器隔离。
次要流程
首先 SpringBoot 我的项目启动,触发监听器,如果引入了 SpringCloud 中的 BootstrapApplicationListener,则开始初始化 SpringCloud 相干的上下文:Bootstrap ApplicationContext,将其设置为先人容器,而后持续创立其子容器:SpringBoot Application。
说说分布式系统开发的痛点,业界是怎么设计的这些解决方案
首先分布式系统开发,目前支流的架构就是微服务架构,如果说你做微服务架构的话,无论你怎么去选型,怎么去设计,首先你总归要碰到以下的几个问题
- 这么多的服务,客户端如何去拜访,你就好比说咱们几百个服务,难道前端要在代码中调用几百个地址,而况服务地址多了,咱们也不好去治理这些 ip 和端口,
- 服务与服务之间,如何去通信,那是不是得解决咱们服务外部之间的调用形式,
- 服务挂了怎么办,你不能因为一个服务挂了,导致整个我的项目呈现问题,导致服务雪崩吧
- 服务与服务是如何做到服务的发现与注册的,你不能说那个服务挂了,我是如何去告诉其余服务的。也就是服务的治理
说说你们公司的 SpringCloud 的组件吧
- Spring Cloud 外围组件:Eureka 服务发现和注册核心
- Spring Cloud 外围组件:Feign 服务与服务间接的调用
- Spring Cloud 外围组件:Ribbon 负载平衡
- Spring Cloud 外围组件:Hystrix 熔断 降级
- Spring Cloud 外围组件:Zuul SpringCloudGateway 服务网关
聊聊 Eureka 吧
首先什么是 Eureka
首先,eureka 在 springcloud 中充当服务注册性能,相当于 dubbo+zk 外面得 zk,然而比 zk 要简略得多,zk 能够做得货色太多了,包含分布式锁,分布式队列都是基于 zk 外面得四种节点加 watch 机制通过长连贯来实现得,然而 eureka 不一样,eureka 是基于 HTTprest 来实现的,就是把服务的信息放到一个 ConcurrentHashMap 中,而后服务启动的时候去读取这个 map,来把所有服务关联起来,而后服务器之间调用的时候通过信息,进行 http 调用。eureka 包含两局部,一部分就是服务提供者(对于 eureka 来说就是客户端),一部分是服务端,客户端须要每个读取每个服务的信息,而后注册到服务端,很显著了,这个服务端就是承受客户端提供的本身的一些信息。目前 eureka 是 ap 的 然而呢 zk 是 cp 的,至于分布式实践下次有空再聊哈。
聊聊 eureka 中一些重要的概念呗
在 Eureka 的服务治理中,会波及到上面一些概念:
- 服务注册:Eureka Client 会通过发送 REST 申请的形式向 Eureka Server 注册本人的服务,提供本身的元数据,比方 ip 地址、端口、运行状况指标的 url、主页地址等信息。Eureka Server 接管到注册申请后,就会把这些元数据信息存储在一个双层的 Map 中。
- 服务续约:在服务注册后,Eureka Client 会保护一个心跳来继续告诉 Eureka Server,阐明服务始终处于可用状态,避免被剔除。Eureka Client 在默认的状况下会每隔 30 秒发送一次心跳来进行服务续约。
- 服务同步:Eureka Server 之间会相互进行注册,构建 Eureka Server 集群,不同 Eureka Server 之间会进行服务同步,用来保障服务信息的一致性。
- 获取服务:服务消费者(Eureka Client)在启动的时候,会发送一个 REST 申请给 Eureka Server,获取下面注册的服务清单,并且缓存在 Eureka Client 本地,默认缓存 30 秒。同时,为了性能思考,Eureka Server 也会保护一份只读的服务清单缓存,该缓存每隔 30 秒更新一次。
- 服务调用:服务消费者在获取到服务清单后,就能够依据清单中的服务列表信息,查找到其余服务的地址,从而进行近程调用。Eureka 有 Region 和 Zone 的概念,一个 Region 能够蕴含多个 Zone,在进行服务调用时,优先拜访处于同一个 Zone 中的服务提供者。
- 服务下线:当 Eureka Client 须要敞开或重启时,就不心愿在这个时间段内再有申请进来,所以,就须要提前先发送 REST 申请给 Eureka Server,通知 Eureka Server 本人要下线了,Eureka Server 在收到申请后,就会把该服务状态置为下线(DOWN),并把该下线事件流传进来。
- 服务剔除:有时候,服务实例可能会因为网络故障等起因导致不能提供服务,而此时该实例也没有发送申请给 Eureka Server 来进行服务下线,所以,还须要有服务剔除的机制。Eureka Server 在启动的时候会创立一个定时工作,每隔一段时间(默认 60 秒),从以后服务清单中把超时没有续约(默认 90 秒)的服务剔除。
- 自我爱护:既然 Eureka Server 会定时剔除超时没有续约的服务,那就有可能呈现一种场景,网络一段时间内产生了异样,所有的服务都没可能进行续约,Eureka Server 就把所有的服务都剔除了,这样显然不太正当。所以,就有了自我爱护机制,当短时间内,统计续约失败的比例,如果达到肯定阈值,则会触发自我爱护的机制,在该机制下,Eureka Server 不会剔除任何的微服务,等到失常后,再退出自我爱护机制。
从这些概念中,就能够晓得大体的流程,Eureka Client 向 Eureka Server 注册,并且保护心跳来进行续约,如果长时间不续约,就会被剔除。Eureka Server 之间进行数据同步来造成集群,Eureka Client 从 Eureka Server 获取服务列表,用来进行服务调用,Eureka Client 服务重启前调用 Eureka Server 的接口进行下线操作。
说说 Eureka 的一些原理和服务流程
服务提供者
1、启动后,向注册核心发动 register 申请,注册服务
2、在运行过程中,定时向注册核心发送 renew 心跳,证实“我还活着”。
3、进行服务提供者,向注册核心发动 cancel 申请,清空以后服务注册信息。
服务消费者
1、启动后,从注册核心拉取服务注册信息
2、在运行过程中,定时更新服务注册信息。
3、服务消费者发动近程调用:
注册核心
1、启动后,从其余节点拉取服务注册信息(节点之间的数据同步)。
2、运行过程中,定时运行 evict 工作,剔除没有按时 renew 的服务(包含非正常进行和网络故障的服务)。
3、运行过程中,接管到的 register、renew、cancel 申请,都会同步至其余注册核心节点。
聊聊 Eureka 的存储机制
既然是服务注册核心,必然要存储服务的信息,咱们晓得 ZK 是将服务信息保留在树形节点上。而上面是 Eureka 的数据存储构造:
Eureka 的数据存储分了两层:数据存储层和缓存层。Eureka Client 在拉取服务信息时,先从缓存层获取(相当于 Redis),如果获取不到,先把数据存储层的数据加载到缓存中(相当于 Mysql),再从缓存中获取。值得注意的是,数据存储层的数据结构是服务信息,而缓存中保留的是通过解决加工过的、能够间接传输到 Eureka Client 的数据结构。
Eureka 实现了二级缓存来保留行将要对外传输的服务信息,数据结构完全相同。
一级缓存:ConcurrentHashMap<Key,Value> readOnlyCacheMap,实质上是 HashMap,无过期工夫,保留服务信息的对外输入数据结构。
二级缓存:Loading<Key,Value> readWriteCacheMap,实质上是 guava 的缓存,蕴含生效机制,保留服务信息的对外输入数据结构。
Eureka 的服务续约机制
服务注册后,要定时(默认 30S,可本人配置)向注册核心发送续约申请,通知注册核心“我还活着”。
注册核心收到续约申请后:
1、更新服务对象的最近续约工夫,即 Lease 对象的 lastUpdateTimestamp;
2、同步服务信息,将此事件同步至其余的 Eureka Server 节点。
Eureka 服务登记机制
服务失常进行之前会向注册核心发送登记申请,通知注册核心“我要下线了”。
注册核心服务接管到 cancel 申请后:
1、删除服务信息,将服务信息从 registry 中删除;
2、更新队列,将此事件增加到更新队列中,供 Eureka Client 增量同步服务信息应用。
3、清空二级缓存,即 readWriteCacheMap,用于保证数据的一致性。
4、更新阈值,供剔除服务应用。
5、同步服务信息,将此事件同步至其余的 Eureka Server 节点。
Eureka 自我爱护
Eureka 自我爱护机制是为了避免误杀服务而提供的一个机制。Eureka 的自我爱护机制“虚心”的认为如果大量服务都续约失败,则认为是本人出问题了(如本人断网了),也就不剔除了;反之,则是 Eureka Client 的问题,须要进行剔除。而自我爱护阈值是辨别 Eureka Client 还是 Eureka Server 出问题的临界值:如果超出阈值就示意大量服务可用,大量服务不可用,则断定是 Eureka Client 出了问题。如果未超出阈值就示意大量服务不可用,则断定是 Eureka Server 出了问题。
聊聊 feign 是啥
Feign 是一种申明式、模板化的 HTTP 客户端(仅在 Application Client 中应用)。申明式调用是指,就像调用本地办法一样调用近程办法,无需感知操作近程 http 申请。Spring Cloud 的申明式调用, 能够做到应用 HTTP 申请近程服务时能就像调用本地办法一样的体验,开发者齐全感知不到这是近程办法,更感知不到这是个 HTTP 申请。Feign 的利用,让 Spring Cloud 微服务调用像 Dubbo 一样,Application Client 间接通过接口办法调用 Application Service,而不须要通过惯例的 RestTemplate 结构申请再解析返回数据。它解决了让开发者调用近程接口就跟调用本地办法一样,无需关注与近程的交互细节,更无需关注分布式环境开发。
聊聊 Feign 的原理呗
咱们来想想平时咱们应用 feign 的时候,会是一个怎么样的流程
- 增加了 Spring Cloud OpenFeign 的依赖
- 在 SpringBoot 启动类上增加了注解 @EnableFeignCleints
- 依照 Feign 的规定定义接口 DemoService,增加 @FeignClient 注解
- 在须要应用 Feign 接口 DemoService 的中央,间接利用 @Autowire 进行注入
- 应用接口实现对服务端的调用
那咱们基于这些步骤来剖析剖析,本文并不会说十分深刻去看每一行的源码
- SpringBoot 利用启动时,由针对 @EnableFeignClient 这一注解的解决逻辑触发程序扫描 classPath 中所有被 @FeignClient 注解的类,这里以 XiaoLiuLiuService 为例,将这些类解析为 BeanDefinition 注册到 Spring 容器中
- Sping 容器在为某些用的 Feign 接口的 Bean 注入 XiaoLiuLiuService 时,Spring 会尝试从容器中查找 XiaoLiuLiuService 的实现类
- 因为咱们素来没有编写过 XiaoLiuLiuService 的实现类,下面步骤获取到的 XiaoLiuLiuService 的实现类必然是 feign 框架通过扩大 spring 的 Bean 解决逻辑,为 XiaoLiuLiuService 创立一个动静接口代理对象,这里咱们将其称为 XiaoLiuLiuServiceProxy 注册到 spring 容器中。
- Spring 最终在应用到 XiaoLiuLiuService 的 Bean 中注入了 XiaoLiuLiuServiceProxy 这一实例。
- 当业务申请实在产生时,对于 XiaoLiuLiuService 的调用被对立转发到了由 Feign 框架实现的 InvocationHandler 中,InvocationHandler 负责将接口中的入参转换为 HTTP 的模式,发到服务端,最初再解析 HTTP 响应,将后果转换为 Java 对象,予以返回。
其实就是基于 aop 代理和面向切面编程,把那些反复的货色,帮咱们封装了起来,而后再联合一起其余的组件如负载平衡 Ribbon 等。
Hystrix 是什么
在分布式系统中,每个服务都可能会调用很多其余服务,被调用的那些服务就是依赖服务,有的时候某些依赖服务呈现故障也是很失常的。
Hystrix 能够让咱们在分布式系统中对服务间的调用进行管制,退出一些调用提早或者依赖故障的容错机制。
Hystrix 通过将依赖服务进行资源隔离,进而阻止某个依赖服务呈现故障时在整个零碎所有的依赖服务调用中进行蔓延;同时 Hystrix 还提供故障时的 fallback 降级机制。
总而言之,Hystrix 通过这些办法帮忙咱们晋升分布式系统的可用性和稳定性。
hystrix 实现原理
hystrix 语义为“豪猪”,具备自我爱护的能力。hystrix 的呈现即为解决雪崩效应,它通过四个方面的机制来解决这个问题
- 隔离(线程池隔离和信号量隔离):限度调用分布式服务的资源应用,某一个调用的服务呈现问题不会影响其余服务调用。
- 优雅的降级机制:超时降级、资源有余时 (线程或信号量) 降级,降级后能够配合降级接口返回托底数据。
- 融断:当失败率达到阀值主动触发降级(如因网络故障 / 超时造成的失败率高),熔断器触发的疾速失败会进行疾速复原。
- 缓存:提供了申请缓存、申请合并实现。
- 反对实时监控、报警、管制(批改配置)
聊聊 hystrix 的隔离机制
- 线程池隔离模式:应用一个线程池来存储以后的申请,线程池对申请作解决,设置工作返回解决超时工夫,沉积的申请沉积入线程池队列。这种形式须要为每个依赖的服务申请线程池,有肯定的资源耗费,益处是能够应答突发流量(流量洪峰来长期,解决不完可将数据存储到线程池队里缓缓解决)
- 信号量隔离模式:应用一个原子计数器(或信号量)来记录以后有多少个线程在运行,申请来先判断计数器的数值,若超过设置的最大线程个数则抛弃改类型的新申请,若不超过则执行计数操作申请来计数器 +1,申请返回计数器 -1。这种形式是严格的控制线程且立刻返回模式,无奈应答突发流量(流量洪峰来长期,解决的线程超过数量,其余的申请会间接返回,不持续去申请依赖的服务)
聊聊 hystrix 的融断机制 和降级
熔断器模式定义了熔断器开关互相转换的逻辑。
- 服务的健康状况 = 申请失败数 / 申请总数。熔断器开关由敞开到关上的状态转换是通过以后服务健康状况和设定阈值比拟决定的。
- 当熔断器开关敞开时,申请被容许通过熔断器。如果以后健康状况高于设定阈值,开关持续放弃敞开。如果以后健康状况低于设定阈值,开关则切换为关上状态。当熔断器开关关上时,申请被禁止通过。当熔断器开关处于关上状态,通过一段时间后,熔断器会主动进入半开状态,这时熔断器只容许一个申请通过。当该申请调用胜利时,熔断器复原到敞开状态。若该申请失败,熔断器持续放弃关上状态,接下来的申请被禁止通过。
- 熔断器的开关能保障服务调用者在调用异样服务时,疾速返回后果,防止大量的同步期待,并且熔断器能在一段时间后持续侦测申请执行后果,提供复原服务调用的可能。
降级须要对上层依赖的业务分级,把产生故障的丢了,换一个轻量级的计划,是一种退而求其次的办法,说白了就是咱们代码中常常用到的 fallback,比如说间接返回一个动态的常量之类的。
什么是网关
网关是整个微服务 API 申请的入口,负责拦挡所有申请,散发到服务下来。能够实现日志拦挡、权限管制、解决跨域问题、限流、熔断、负载平衡,暗藏服务端的 ip,黑名单与白名单拦挡、受权等,罕用的网关有 zuul(netflix 的,然而曾经停更了)和 spring cloud gateway (springcloudalibaba)。这里次要讲 springcloud gateway,springcloud gateway 是一个全新的我的项目, 其基于 spring5.0 以及 springboot2.0 和我的项目 Reactor 等技术开发的网关, 其次要的目标是为微服务架构提供一种简略无效的 API 路由治理形式.
综上:个别状况下,网关个别都会提供申请转发、平安认证(身份 / 权限认证)、流量管制、负载平衡、容灾、日志、监控这些性能。
聊聊 Spring Cloud Gateway 的大抵流程
- 路由的配置转换为 routeDefinition
- 获取申请对应的路由规定, 将 RouteDefinition 转换为 Route
- 执行 Predicate 判断是否合乎路由, 以及执行相干的过滤(全局过滤器以及路由过滤器)
- 负载平衡过滤器负责将申请中的 serviceId 转换为具体的服务实例 Ip
其实网关其实还有很多说的,因为网关企业级的网关分类比拟多,比方咱们的对外网关 对内网关,对合作伙伴的网关等
网关的设计方案
- 基于 Nginx+Lua+ OpenResty 的计划,能够看到 Kong,orange 都是基于这个计划
- 基于 Netty、非阻塞 IO 模型。通过网上搜寻能够看到国内的宜人贷等一些公司是基于这种计划,是一种成熟的计划。
- 基于 Node.js 的计划。这种计划是利用了 Node.js 天生的非阻塞的个性。
- 基于 java Servlet 的计划。zuul 基于的就是这种计划,这种计划的效率不高,这也是 zuul 总是被诟病的起因。
最初问一个问题,mysql 分库分表下的数据迁徙问题
问题场景:就是比如说咱们一开始设计架构的时候,咱们并不知道这个我的项目能火,然而忽然老板拿到了融资,而后数据量起来,原来的架构抗不住了,这个时候须要分库分表了,你怎么去迁徙,怎么保障迁徙之后的数据一致性
停机部署法
大抵思路就是,挂一个布告,中午停机降级,而后中午把服务停了,跑数据迁徙程序,进行数据迁徙。步骤如下:
- 出一个布告,比方“今晚 00:00~6:00 进行停机保护,暂停服务”
- 写一个迁徙程序,读 db-old 数据库,通过中间件写入新库
- 而后测试一下数据的一致性
大家不要感觉这种办法 low,我其实始终感觉这种办法可靠性很强。而且我置信大部分公司肯定不是什么很牛逼的互联网公司,如果你们的产品凌晨 1 点的用户沉闷数还有超过 1000 的,你们握个爪!毕竟不是所有人都在什么电商公司的,大部分产品中午都没啥流量。所以此计划,并非没有可取之处。
然而此计划有一个毛病,累!不止身材累,心也累!你想想看,原本定六点完结,你五点把数据库迁徙好,然而不知怎么滴,程序切新库就是有点问题。于是,眼瞅着天就要亮了,连忙把数据库切回老库。第二个早晨持续这么干,几乎是身心俱疲。ps:这里教大家一些技巧啊,如果你真的没做过分库分表,又想吹一波,涨一下工资,倡议答这个计划。因为这个计划比拟 low,low 到没什么货色能够深挖的,所以答这个计划,比拟靠谱。
双写部署法
- 首先咱们用 canal 去监听咱们须要分库分表的那个表,就是上线之后的那些事务操作,而后把它放到队列外面,存起来,先不生产。
- 启动一个程序把旧数据同步到分库分表的数据库,这里有一个问题怎么辨别新旧数据,就是当这个我的项目启动的时候,算出最大的 id, 这个之前的就是老数据了,或者是按更新工夫排序,再这个工夫之前的就是老数据,之后的就是新数据了。
- 最初把迁徙数据下线,再去生产队列,实现数据的迁徙
- 测试验证数据是否失常
完结
上面咱们来看看分布式的实践和 Zk,对于分布式系统开发还是须要明确的。
日常求赞
好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是 真粉。
创作不易,各位的反对和认可,就是我创作的最大能源,咱们下篇文章见
微信 搜 “ 六脉神剑的程序人生 ” 回复 888 有我找的许多的材料送给大家