微服务注册中心:Consul——服务发现

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"系列文章:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/2636d77e2fe433e8144680eac","title":"","type":null},"content":[{"type":"text","text":"微服务架构:网关概念与 zuul","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/4154bb63f82f17b02e2dca2fb","title":"","type":null},"content":[{"type":"text","text":"微服务网关:Spring Cloud Gateway —— Zuul","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/96b51e801ac0fa2b8b59f9991","title":"","type":null},"content":[{"type":"text","text":"微服务网关:Spring Cloud Config- 配置中心","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/8f23ba021e573e876df221c6f","title":"","type":null},"content":[{"type":"text","text":"微服务网关方案:Kong & Nacos","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/4db8d97e7ca4f1ab679e4d0f3","title":"","type":null},"content":[{"type":"text","text":"Nacos 实践","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/68c7c9ec4d99aab16315736d2","title":"","type":null},"content":[{"type":"text","text":"微服务网关:Nacos 源码实践(二)","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/61b260b61df452bd6fa47cbbb","title":"","type":null},"content":[{"type":"text","text":"微服务注册中心:Consul——概念与基础操作","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/958de779686fa98c3ac22c5b5","title":"","type":null},"content":[{"type":"text","text":"微服务注册中心:Consul——服务注册","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"一 概述","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 说完了Consul的服务注册,那么就该到服务发现了。大家有过rpc框架使用经验的,例如nacos、eureka、dubbo等,就会了解服务中的角色,也就是生产者和消费者,也可以理解为服务的提供方和服务使用方。服务注册,是服务提供方把自己的信息(ip、端口、方法、参数&返回值信息)注册到一个中心;服务发现就是服务使用方,从中心获取到可用的服务提供方信息,并像本地方法调用一样调用其方法(远程方法),这也就是RPC(远程方法调用)的过程。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"二 Consul宏观架构","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 这里先说一下consul的架构,Consul的宏观架构如下图所示:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/70/70263786e0b197a268324b81028ca38e.png","alt":"Consul架构","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 其中\"DATACENTER1\"和 “DATACENTER2”代表两个数据中心(Consul对多数据中心天然有比较好的支持)。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 在每个数据中心内有","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Client","attrs":{}},{"type":"text","text":"和","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Server","attrs":{}},{"type":"text","text":"的混合。通常我们会部署","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"3~5","attrs":{}},{"type":"text","text":"台Server。具体数量由","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"可用性","attrs":{}},{"type":"text","text":"和","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"性能","attrs":{}},{"type":"text","text":"之间取得平衡,因为随着机器的增加,共识的速度会逐渐变慢。不过对Client的数量通常没有限制,可以轻松地扩展到数千或数万的量级。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 所有在数据中心的代理都会参与一个Gossip协议,这意味着有一个Gossip池,其中包含了某个数据中心的所有","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Agent","attrs":{}},{"type":"text","text":"。这有几个目的:","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第一,客户端不需要配置Server的地址,发现工作是自动完成的。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第二,检测代理故障的工作不放在Server上,而是分布式的。这使得故障检测的扩展性比原生的心跳方案要强得多。同时,它还为节点提供了故障检测,如果代理无法到达,那么该节点可能已经发生了故障。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第三,它被用作消息层,当发生重要事件(如Leader 选举)时进行通知。","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 每个数据中心的Server都是单一Raft对等集的一部分。这意味着它们共同选出一个单一的Leader,一个被选中的Server,它有额外的职责。","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Leader负责处理所有查询和事务","attrs":{}},{"type":"text","text":"。事务也必须复制到所有参与共识协议的分片。由于这一要求,当","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"None-Leader Server","attrs":{}},{"type":"text","text":"收到RPC请求时,它会将其转发给集群Leader。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 一般情况下,","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"不同的Consul数据中心之间不会复制数据","attrs":{}},{"type":"text","text":"。当对另一个数据中心的资源进行请求时,本地Consul服务器会将该资源的RPC请求转发给远程Consul服务器,并返回结果。如果远程数据中心不可用,那么这些资源也将不可用,但这不会以其他方式影响本地数据中心。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"三 Consul服务发现","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"3.1 Consul已注册服务查看","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 大概了解了Consul的架构,接下来回到本篇的主题,我们先搞清楚怎样获取到已注册的服务,来供调用。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 如果还不了解服务注册怎样实现,大家先再看一下这篇文章:","attrs":{}},{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/958de779686fa98c3ac22c5b5","title":"","type":null},"content":[{"type":"text","text":"微服务注册中心:Consul——服务注册","attrs":{}}]},{"type":"text","text":",可以直接拉取gitee代码到本地,本地启动Consul服务后,再启动springboot-consul下的SpringBootConsulApplication,即可完成注册。注意一下consul服务端口,默认使用的是8500。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/6e/6e5e81122ceeade4117a6fc3e31d50c8.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果上述操作完成且没有问题,那么我们在浏览器中查看http://localhost:8500/,可以看到Consul下的Services信息如下:","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/be/be790a2c05eb972a03a7de218a40cf18.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"会有两个Service,一个是consul——这个是Consul服务启动后就有的,自带的service; 下面的first-consul-client就是我们启动并注册的服务。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"3.2 建立消费者工程","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3.2.1 创建工程","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 创建一个名为springboot-consul-consumer的maven工程。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3.2.2 依赖配置","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 主要是spring-cloud,spring boot,以及spring-cloud-starter-consul-discovery,用于做consul的服务发现。pom.xml内容如下:","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"\n \n UTF-8\n UTF-8\n 1.0.0\n 1.8\n Finchley.RELEASE\n \n\n \n \n org.springframework.boot\n spring-boot-starter-actuator\n \n \n org.springframework.cloud\n spring-cloud-starter-netflix-hystrix-dashboard\n \n \n org.springframework.cloud\n spring-cloud-starter-consul-discovery\n \n \n org.springframework.cloud\n spring-cloud-starter-openfeign\n \n \n org.springframework.boot\n spring-boot-starter-web\n \n \n org.springframework.boot\n spring-boot-starter-test\n test\n \n \n\n \n \n \n org.springframework.cloud\n spring-cloud-dependencies\n ${spring-cloud.version}\n pom\n import\n \n \n ","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3.2.3 application属性配置","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这里尝试使用application.yml,zipkin不是必须,所以暂时注释掉:","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"server:\n port: 8521\nspring:\n application:\n name: spring-cloud-consul-consumer\n cloud:\n consul:\n host: localhost\n port: 8500\n discovery:\n serviceName: ${spring.application.name}\t# 注册到consul的服务名称\n # zipkin:\n # base-url: http://localhost:9411/\n sleuth:\n sampler:\n probability: 1 #样本采集量,默认为0.1,为了测试这里修改为1,正式环境一般使用默认值\n#ribbon 负载均衡策略配置, service-producer为注册的服务名\nservice-producer:\n ribbon:\n NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule\n#开启熔断器\nfeign:\n hystrix:\n enabled: true","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3.2.4 核心代码","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)必不可少的启动文件ConsulConsumerApplication:","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"\n@EnableFeignClients\n@EnableDiscoveryClient\n@SpringBootApplication\npublic class ConsulConsumerApplication {\n\n public static void main(String[] args) {\n SpringApplication.run(ConsulConsumerApplication.class, args);\n }\n\n @Bean\n @LoadBalanced\n public RestTemplate restTemplate() {\n return new RestTemplate();\n }\n\n // 此配置是为了服务监控而配置,与服务容错本身无关,\n // ServletRegistrationBean因为springboot的默认路径不是\"/hystrix.stream\",\n // 只要在自己的项目里配置上下面的servlet就可以了\n @Bean\n public ServletRegistrationBean getServlet() {\n HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();\n ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);\n registrationBean.setLoadOnStartup(1);\n registrationBean.addUrlMappings(\"/hystrix.stream\");\n registrationBean.setName(\"HystrixMetricsStreamServlet\");\n return registrationBean;\n }\n\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)访问服务方法","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.cloud.client.discovery.DiscoveryClient;\nimport org.springframework.cloud.client.loadbalancer.LoadBalancerClient;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class ServiceController {\n\n @Autowired\n private LoadBalancerClient loadBalancerClient;\n @Autowired\n private DiscoveryClient discoveryClient;\n\n private String serviceId = \"first-consul-client\";\n\n /**\n * 获取所有服务\n */\n @RequestMapping(\"/services\")\n public Object services() {\n return discoveryClient.getInstances(serviceId);\n }\n\n /**\n * 从所有服务中选择一个服务(轮询)\n */\n @RequestMapping(\"/discover\")\n public Object discover() {\n return loadBalancerClient.choose(serviceId).getUri().toString();\n }\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"至此,工程建立完毕。可见,核心逻辑还是在引入的依赖包spring-cloud-starter-consul-discovery中。consul服务配置在了application.yml中的consul属性,controller中通过设置的serviceId来定位我们要使用的服务。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/fb/fb880dee7a09b2de66b09c1ecd761dcc.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"3.3 启动验证","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 启动ConsulConsumerApplication,完成后,通过/services来验证是否能够获取到服务列表,浏览器中输入: http://localhost:8521/services,返回信息为:","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/8f/8f9536fc85822c8a364eddff5df43d3d.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可见确实得到了预期的结果。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"再次查看Consul的ui页面(http://localhost:8500/ui/dc1/services):","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/05/05d60927e87923ccb2d296f1b4049891.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"标红的就是我们刚刚启动的消费者,也注册到了Consul的services列表中。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上述代码已提交至gitee: https://gitee.com/flamingskyline/spring-boot-integration,可自行拉取并做调整。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"四 小结","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 至此,我们从本地安装启动Consul,到服务注册和发现,可以简单的使用起来了,但还是非常简单的应用,并未深入到原理和架构,后面的文章中,将会对其原理进行分析,敬请期待。","attrs":{}}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章