<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>名字服务 on 子恒的博客</title>
    <link>http://chestnutheng.github.io/tags/%E5%90%8D%E5%AD%97%E6%9C%8D%E5%8A%A1/</link>
    <description>Recent content in 名字服务 on 子恒的博客</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Thu, 16 Jul 2020 20:10:14 +0800</lastBuildDate>
    <atom:link href="http://chestnutheng.github.io/tags/%E5%90%8D%E5%AD%97%E6%9C%8D%E5%8A%A1/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>[后台]负载均衡（二）能力篇</title>
      <link>http://chestnutheng.github.io/load_balance2/</link>
      <pubDate>Thu, 21 May 2020 17:18:55 +0800</pubDate>
      <guid>http://chestnutheng.github.io/load_balance2/</guid>
      <description>&lt;h1 id=&#34;名字服务&#34;&gt;名字服务&lt;/h1&gt;&#xA;&lt;h2 id=&#34;基础设计&#34;&gt;基础设计&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;http://jm.taobao.org/2018/06/26/%E8%81%8A%E8%81%8A%E5%BE%AE%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%8E%E5%8F%91%E7%8E%B0/&#34;&gt;名字服务考虑的基本设计&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;客户端发现：&lt;br&gt;&#xA;服务提供者的实例在启动时或者位置信息发生变化时会向服务注册表注册自身，在停止时会向服务注册表注销自身，如果服务提供者的实例发生故障，在一段时间内不发送心跳之后，也会被服务注册表注销。&lt;br&gt;&#xA;服务消费者的实例会向服务注册表查询服务提供者的位置信息，然后通过这些位置信息直接向服务提供者发起请求。&lt;/p&gt;&#xA;&lt;p&gt;服务端发现：&lt;br&gt;&#xA;第一步与客户端发现相同。&lt;br&gt;&#xA;服务消费者不直接向服务注册表查询，也不直接向服务提供者发起请求，而是将对服务提供者的请求发往一个中央路由器或者负载均衡器，中央路由器或者负载均衡器查询服务注册表获取服务提供者的位置信息，并将请求转发给服务提供者。&lt;/p&gt;&#xA;&lt;p&gt;这两种模式各有利弊，客户端发现模式的优势是，服务消费者向服务提供者发起请求时比服务端发现模式少了一次网络跳转，劣势是服务消费者需要内置特定的服务发现客户端和服务发现逻辑；&lt;br&gt;&#xA;服务端发现模式的优势是服务消费者无需内置特定的服务发现客户端和服务发现逻辑，劣势是多了一次网络跳转，并且需要基础设施环境提供中央路由机制或者负载均衡机制。目前客户端发现模式应用的多一些，因为这种模式的对基础设施环境没有特殊的要求，和基础设施环境也没有过多的耦合性。&lt;br&gt;&#xA;主调调用被调时，根据被调的名字从服务注册中心获取服务实例列表，包括节点ip、端口、权重、地理位置等；一般采取分钟级别的定时任务去拉取，本地做缓存，异步更新。&lt;/p&gt;&#xA;&lt;p&gt;实现方式&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;DNS，传播速度太慢，没法发现端口。SkyDNS解决了这个问题，在k8s里大量使用&lt;/li&gt;&#xA;&lt;li&gt;zookeeper或者etcd，如SmartStack，能保证强一致，但是要做很多开发&lt;/li&gt;&#xA;&lt;li&gt;Eureka。Netflix的java生态里的优秀方案&lt;/li&gt;&#xA;&lt;li&gt;Consul，提供服务配置、服务的内存和磁盘监测等&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;服务注册信息&#34;&gt;服务注册信息&lt;/h2&gt;&#xA;&lt;h3 id=&#34;ip和端口&#34;&gt;IP和端口&lt;/h3&gt;&#xA;&lt;p&gt;一个服务端要接入名字服务，必须要先提供自己的IP和端口信息。&lt;br&gt;&#xA;IP的获取方法：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;通过遍历网卡的方式去获取，找到第一个不为本地环回地址的 IP 地址。dubbo就是这种方法&lt;/li&gt;&#xA;&lt;li&gt;指定网卡名interfaceName，来获取IP&lt;/li&gt;&#xA;&lt;li&gt;直接与服务注册中心建立 socket 连接，然后通过socket.getLocalAddress() 这种方式来获取本机的 IP&lt;br&gt;&#xA;端口的获取方法：&lt;br&gt;&#xA;一般的RPC服务或者Web服务监听的端口都在配置中写好，可以直接获取上报。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;扩展设计&#34;&gt;扩展设计&lt;/h3&gt;&#xA;&lt;p&gt;除了IP和端口，可能还有一些常用的服务信息需要注册上来，提供更高级的功能：&lt;br&gt;&#xA;1.支持TLS：想知道某个 HTTP 服务是否开启了 TLS。&lt;br&gt;&#xA;2.权重：对相同服务下的不同节点设置不同的权重，进行流量调度。&lt;br&gt;&#xA;3.环境分配：将服务分成预发环境和生产环境，方便进行AB Test功能。&lt;br&gt;&#xA;4.机房：不同机房的服务注册时加上机房的标签，以实现同机房优先的路由规则。&lt;/p&gt;&#xA;&lt;h2 id=&#34;无损注册下线&#34;&gt;无损注册/下线&lt;/h2&gt;&#xA;&lt;p&gt;虽然服务注册一般发生在服务的启动阶段，但是细分的话，服务注册应该在服务已经完全启动成功，并准备对外提供服务之后才能进行注册。&lt;br&gt;&#xA;1.有些 RPC 框架自身提供了方法来判断服务是否已经启动完成，如 Thrift ，我们可以通过 Server.isServing() 来判断。&lt;br&gt;&#xA;2.有一些 RPC 框架本身没有提供服务是否启动完成的方式，这时我们可以通过检测端口是否已经处于监听状态来判断。&lt;br&gt;&#xA;3.而对于 HTTP 服务，服务是否启动完毕也可以通过端口是否处于监听状态来判断。&lt;br&gt;&#xA;下线也是一样的，可以注册服务下线的回调，或者监听服务下线的信号，或者做健康检查&lt;/p&gt;&#xA;&lt;h2 id=&#34;健康检查&#34;&gt;健康检查&lt;/h2&gt;&#xA;&lt;p&gt;客户端主动心跳上报健康：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;客户端每隔一定时间主动发送“心跳”的方式来向服务端表明自己的服务状态正常，心跳可以是 TCP 的形式，也可以是 HTTP 的形式。&lt;/li&gt;&#xA;&lt;li&gt;也可以通过维持客户端和服务端的一个 socket 长连接自己实现一个客户端心跳的方式。&lt;br&gt;&#xA;客户端的健康检查只能表明网络可达，不能代表服务可用。服务端的健康检查可以准确获得服务的健康状态：&lt;/li&gt;&#xA;&lt;li&gt;服务端调用服务发布者某个 HTTP 接口来完成健康检查。&lt;/li&gt;&#xA;&lt;li&gt;对于没有提供 HTTP 服务的 RPC 应用，服务端调用服务发布者的接口来完成健康检查。&lt;/li&gt;&#xA;&lt;li&gt;可以通过执行某个脚本的形式来进行综合检查，覆盖多个场景。&lt;br&gt;&#xA;服务端检查也有问题，一个是调用服务的方式不通用，需要额外实现，还有就是服务注册中心可能和服务的网络不互通。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;节点变化通知&#34;&gt;节点变化通知&lt;/h2&gt;&#xA;&lt;p&gt;当服务有节点退出或新的节点加入时，订阅者如何及时收到通知？经典的push和pull的问题&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
