大家好,我是悟空。为了扩大版图,唐朝第二任皇帝唐太宗到处进攻周边小国。连不服的小国也被唐太宗收服了。这些小国后来都需要向唐太宗进贡。贡就是崇拜和贡品。是两国或两国政府之间承认彼此关系的一种礼节性外交。大唐贡图来自百度百科《贞观之治》,指的是唐朝的鼎盛时期。周边的小国被打得落花流水,国家繁荣发展,以惊人的速度成为世界第一强国。唐人街的“唐”指的就是唐朝,足以说明唐朝对世界的影响。小国定期向唐朝进贡。这不就是微服务的心跳机制吗?他们是在告诉唐朝,我还是服从你的管教。然后唐朝就会把这些小国的名称、地址、服饰、容貌,都写进一个附庸国名录里。万一哪天这些小国不服从,就会被除名,以后可能会被攻击~下面是多国致敬示例图:致敬示例图在微服务领域,心跳机制也出现了很多时候,比如Eureka和Naocs中客户端和服务端的服务更新,Redis的主从复制等等,原理其实很相似。本文将以Eureka中的服务续订功能为例,对心跳机制进行分析。对于Eureka,涉及两端,客户端和服务器。客户端相当于我们的订单服务、商品服务等,Eureka服务器是指Eureka注册中心的服务。而守约就是客户端每隔一段时间向服务端发送一次心跳,告诉Eureka服务端它的状态是alive。主要涉及以下知识点:①心跳请求是谁发出的?②多久发送一次?③怎么寄的?④如何接收心跳请求?⑤收到后做了什么?谁发送心跳请求Eureka使用客户端向Eureka服务器发送心跳请求。如下图所示:上图中一共有三个微服务:订单服务、商品服务、优惠券服务,都已经成功注册到Eureka服务器(注册中心)。然后每个微服务都会自己向注册中心发送心跳请求。多久发送一次DISCoveryClient在初始化的时候,会调度一些定时任务。Eureka初始化发送心跳请求的线程池heartbeatExecutor,用于创建发送心跳的线程HeartbeatThread。原理如图:线程池heartbeatExecutor源码如下:线程池有核心参数:maximumPoolSize:最大线程数。线程池允许创建的最大线程数。corePoolSize:核心线程数。当一个任务被提交到线程池时,线程池会创建一个线程来执行这个任务。即使其他空闲的核心线程可以执行新的任务,该线程也会被创建。当要执行的任务数大于线程池的基本大小时,将不再创建。.如果调用了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有的基础线程。keepAliveTime:线程活动保持时间,线程池中工作线程空闲后,保持活动的时间。runnableTaskQueue:任务队列,用于保存等待执行任务的阻塞队列。有四种类型:ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、PriorityBlockingQueue。然后使用这个线程池执行定时调度任务。源代码如下。定时任务启动后,延时30秒发送心跳请求,然后每隔30秒执行一次心跳请求。这里可以看到新建了一个HeartbeatThread线程。更多线程相关知识请阅读这篇文章:多线程核心知识点定时任务如何发送心跳请求?HeartbeatThread线程继承了Runnable类,实现了run方法,会执行发送心跳请求的具体逻辑。直接进入renew()方法,核心逻辑就是这一行:eurekaTransport.registrationClient.sendHeartBeat(instanceInfo.getAppName(),instanceInfo.getId(),instanceInfo,null);调用EurekaHttpClient的sendHeartBeat方法将实例信息发送给注册信息。连接请求URL的示例如下:http://localhost:8080/v2/apps/order/i-000000-1,此请求是PUT请求。如何接收心跳请求?请求从客户端发送心跳请求后,服务端会收到请求。负责接受请求的类是ApplicationsResource,相当于MVC中的Controller。根据请求的URL格式和请求方法(PUT),我们可以发现服务端的方法是InstanceResource.renewLease()。ApplicationsResource->ApplicationResource->InstanceResource收到后做了什么?其中核心代码是renew方法,更新实例的一个字段。这个字段叫做lastupdateTimestamp,就是最后更新的时间。publicvoidrenew(){lastUpdateTimestamp=System.currentTimeMillis()+duration;}心跳机制的实例实际上是从服务器注册表中获取的。它是一个ConcurrentHashmap,以实例名作为key获取值(instance),也就是说实例信息是保存在内存中的。你得到的是一个Lease实例,数据结构是这样的:Lease,有一个volatile修饰字段lastUpdateTimestamp。通过更新这个字段,记录实例信息确实是活着的,刚刚和Eureka通信过。这就像古唐朝的贡品。唐朝周边的小国都需要定期向唐朝进贡。目的是要告诉唐朝,我对唐朝还是有依恋的。那么有了这个字段更新,EurekaServer本身就会有一个定时任务去检查服务实例的最后更新时间。如果过期,则认为实例状态异常,需要下线服务。这是下一篇文章。内容。
