认识Zookeeper是一套分布式协调服务。

  优点:  

    简单:与文件系统类似,Znode的组织方式。

    多副本:一般再线上都是三副本或者五副本的形式,最少会有三个节点。

    有序:有序的操作,根据时间戳进行排序。

    快:读多写少的情况下比较快。

在Spring cloud 中使用Zookeeper最为服务注册中心。

  在pom引入spring-cloud-starter-zookeeper-discovery

        <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>
     <!--dependencyManagement中加入spring cloud dependency-->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
  
    <type>pom</type>
      <scope>import</scope>
</dependency>
</dependencies>

  在application.properties中声明

#告诉服务器找到哪一个zookeeper作为服务注册中心,作为例子,在本地启动了一个2181,在生产中最少使用三副本
spring.cloud.zookeeper.connect-string=localhost:2181

  在bootstarp.properties 中定义

  

spring.application.name=waiter-service

开启DiscoveryClient:@EnableDiscoveryClient

使用zookeeper作为注册中心的问题

  《阿里巴巴为什么不用Zookeeper做服务发现》https://yq.aliyun.com/articles/599997

  《Eureka! Why You Shouldn’t Use ZooKeeper for Service Discovery》.

  核心思想

    在实践中,注册中心不能因为自身的任何原因破坏服务之间本身的可连通性

    注册中心需要AP,而Zookeeper是CP

      CAP:一致性,可用性,分区容忍性

    

通过Docker启动Zookeeper

  官方指引

    https://hub.docker.com/_/zookeeper

  获取镜像

    docker pull zookeeper:3.5

  运行Zookeeper镜像

    docker run --name zookeeper -p 2181:2181 -d zookeeper:3.5

  查看zookeeper日志: docker logs zookeeper

  进入zookeeper容器 : docker exec -it zookeeper bash

  连接zookeeper:./zkCli.sh命令行连接

  

ls
ls [-s] [-w] [-R] path
[zk: localhost:2181(CONNECTED) 1] ls /
[services, zookeeper]
[zk: localhost:2181(CONNECTED) 2] ls /services
[waiter-service]
[zk: localhost:2181(CONNECTED) 3] ls /services/waiter-service
[cb8e9631-f020-4cfa-9236-73025dc04a4d]
[zk: localhost:2181(CONNECTED) 4] ls /services/waiter-service/cb8e9631-f020-4cfa-9236-73025dc04a4d
[]
[zk: localhost:2181(CONNECTED) 5] get /services/waiter-service/cb8e9631-f020-4cfa-9236-73025dc04a4d
{"name":"waiter-service","id":"cb8e9631-f020-4cfa-9236-73025dc04a4d","address":"DESKTOP-JMA2LS2","port":55825,"sslPort":null,"payload":{"@class":"org.springframework.cloud.zookeeper.discovery.ZookeeperInstance","id":"waiter-service-1","name":"waiter-service","metadata":{}},"registrationTimeUTC":1570436655426,"serviceType":"DYNAMIC","uriSpec":{"parts":[{"value":"scheme","variable":true},{"value":"://","variable":false},{"value":"address","variable":true},{"value":":","variable":false},{"value":"port","variable":true}]}}

使用customer来发现zookeeper中注册的writer-service服务

  pom应用

        <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency> <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

在application.properties中定义

server.port=0

#显示所有信息
management.endpoint.health.show-details=always spring.cloud.zookeeper.connect-string=localhost:2181

bootstarp.properties

spring.application.name=customer-service

开启DiscoveryClient: @EnableDiscoveryClient

注入:HttpComponentsClientHttpRequestFactory 以及RestTemplate

@Bean
public HttpComponentsClientHttpRequestFactory requestFactory() {
PoolingHttpClientConnectionManager connectionManager =
new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS);
connectionManager.setMaxTotal(200);
connectionManager.setDefaultMaxPerRoute(20); CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.evictIdleConnections(30, TimeUnit.SECONDS)
.disableAutomaticRetries()
// 有 Keep-Alive 认里面的值,没有的话永久有效
//.setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE)
// 换成自定义的
.setKeepAliveStrategy(new CustomConnectionKeepAliveStrategy())
.build(); HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory(httpClient); return requestFactory;
}
@LoadBalanced
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
.setConnectTimeout(Duration.ofMillis(100))
.setReadTimeout(Duration.ofMillis(500))
.requestFactory(this::requestFactory)
.build();
}
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.http.HttpResponse;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext; import java.util.Arrays; public class CustomConnectionKeepAliveStrategy implements ConnectionKeepAliveStrategy {
private final long DEFAULT_SECONDS = 30; @Override
public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
return Arrays.asList(response.getHeaders(HTTP.CONN_KEEP_ALIVE))
.stream()
.filter(h -> StringUtils.equalsIgnoreCase(h.getName(), "timeout")
&& StringUtils.isNumeric(h.getValue()))
.findFirst()
.map(h -> NumberUtils.toLong(h.getValue(), DEFAULT_SECONDS))
.orElse(DEFAULT_SECONDS) * 1000;
}
}
import geektime.spring.springbucks.customer.model.Coffee;
import geektime.spring.springbucks.customer.model.CoffeeOrder;
import geektime.spring.springbucks.customer.model.NewOrderRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder; import java.util.Arrays;
import java.util.List; @Component
@Slf4j
public class CustomerRunner implements ApplicationRunner {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient; @Override
public void run(ApplicationArguments args) throws Exception {
showServiceInstances();
readMenu();
Long id = orderCoffee();
queryOrder(id);
} /**
* 打印discoveryClient信息
* */
private void showServiceInstances() {
log.info("DiscoveryClient: {}", discoveryClient.getClass().getName());
discoveryClient.getInstances("waiter-service").forEach(s -> {
log.info("Host: {}, Port: {}", s.getHost(), s.getPort());
});
} private void readMenu() {
ParameterizedTypeReference<List<Coffee>> ptr =
new ParameterizedTypeReference<List<Coffee>>() {};
ResponseEntity<List<Coffee>> list = restTemplate
.exchange("http://waiter-service/coffee/", HttpMethod.GET, null, ptr);
list.getBody().forEach(c -> log.info("Coffee: {}", c));
} private Long orderCoffee() {
NewOrderRequest orderRequest = NewOrderRequest.builder()
.customer("Li Lei")
.items(Arrays.asList("capuccino"))
.build();
RequestEntity<NewOrderRequest> request = RequestEntity
.post(UriComponentsBuilder.fromUriString("http://waiter-service/order/").build().toUri())
.body(orderRequest);
ResponseEntity<CoffeeOrder> response = restTemplate.exchange(request, CoffeeOrder.class);
log.info("Order Request Status Code: {}", response.getStatusCode());
Long id = response.getBody().getId();
log.info("Order ID: {}", id);
return id;
} private void queryOrder(Long id) {
CoffeeOrder order = restTemplate
.getForObject("http://waiter-service/order/{id}", CoffeeOrder.class, id);
log.info("Order: {}", order);
}
}

Zookeeper---作为服务注册中心的更多相关文章

  1. 基于ZooKeeper的服务注册中心

    本文介绍基于ZooKeeper的Dubbo服务注册中心的原理. 1.ZooKeeper中的节点 ZooKeeper是一个树形结构的目录服务,支持变更推送,因此非常适合作为Dubbo服务的注册中心. 注 ...

  2. 使用Spring Cloud搭建服务注册中心

    我们在之前的博客中已经介绍过阿里的分布式服务框架dubbo[Linux上安装Zookeeper以及一些注意事项][一个简单的案例带你入门Dubbo分布式框架],但是小伙伴们应该也看到了,阿里的dubb ...

  3. Dubbo学习笔记1:使用Zookeeper搭建服务治理中心

    Zookeeper是Apache Hadoop的子项目,是一个树形的目录服务,支持变更推送,适合作为Dubbo服务的注册中心,工业强度较高,推荐生成环境使用. , 下面结合上图介绍Zookeeper在 ...

  4. lms框架服务注册中心

    服务注册中心原理 在分布式系统里的注册中心.原理是将部署服务的机器地址记录到注册中心,服务消费者在有需求的时候,只需要查询注册中心,输入提供的服务名,就可以得到地址,从而发起调用. 在微服务架构下,主 ...

  5. silky微服务框架服务注册中心介绍

    目录 服务注册中心简介 服务元数据 主机名称(hostName) 服务列表(services) 终结点 时间戳 使用Zookeeper作为服务注册中心 使用Nacos作为服务注册中心 使用Consul ...

  6. 服务注册中心之ZooKeeper系列(一)

    一.服务注册中心介绍 分布式服务框架部署在多台不同的机器上.例如服务A是订单相关的处理服务,服务B是订单的客户的相关信息服务.此时有个需求需要在服务A中获取订单客户的信息.如下图: 此时就面临以下几个 ...

  7. 服务注册中心Eureka vs Zookeeper vs Consul

    前言 在现在云计算和大数据快速发展的今天,业务快速发展和变化.我们以前的单一应用难以应对这种快速的变化, 因此我们需要将以前单一的大应用不断进行差分,分成若干微小的应用或者服务,这就是微服务的思想.但 ...

  8. 作为服务注册中心,Eureka比Zookeeper好在哪里

    CAP是Consistency.Availablity和Partition Tolerance的缩写.一般的分布式系统最多满足其中两条.而Partition Tolerance是分布式系统的关键,因此 ...

  9. 学习一下 SpringCloud (二)-- 服务注册中心 Eureka、Zookeeper、Consul、Nacos

    (1) 相关博文地址: 学习一下 SpringCloud (一)-- 从单体架构到微服务架构.代码拆分(maven 聚合): https://www.cnblogs.com/l-y-h/p/14105 ...

随机推荐

  1. slot-scope 插槽 的使用 ——'<template slot-scope="page">'

    slot-scope="page"slot-scope 是一个插槽,拿外面的数据,可以获取当前一行的数据page.row.pageId 拿到当前行数据的pageId注意:slot- ...

  2. Sql中使用Case when

    SELECT CASE WHEN Column IS NOT NULL THEN '情况1' ELSE '情况2' END AS '列名' , FROM dbo.Table

  3. BZOJ-1907 树的路径覆盖 贪心

    题意:给一个n个点的树,求树的最小路径覆盖.(这个最小路径覆盖不能有重点) 解法:往图论方向想很久,想得太复杂了,其实直接贪心.这个大佬题解写得很好: https://blog.csdn.net/bl ...

  4. 三、ARM 寄存器及异常处理

    3.1 ARM 内部寄存器 ARM920T 总共有 37 个寄存器,其中 31 通用 32 位寄存器和 6 个状态寄存器,但不能在同一时刻对所有的寄存器可见.处理器状态和运行模式决定了哪些寄存器对程序 ...

  5. LeetCode--046--全排列(java)

    给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1 ...

  6. python——解释型语言

    编程语言分三大类   :  低级语言  .  汇编语言 .   高级语言. 现代计算机都是基于  图灵机模型 制造的.  因此计算机的内部只能接受二进制数据.而用二进制代码  0  1  描述的指令叫 ...

  7. nginx之访问静态文件

    如何配置nginx,访问服务器上的静态文件? 1.在目录/data/interface_test下创建静态文件queryAppData.json,内容如下: 如何访问该文件呢? 2.修改/usr/lo ...

  8. mysql中各种连接的区别

    现在有如下两个表: A表. B表. 一:使用笛卡尔连接 SELECT * FROM a,b 结果: 二:内连接 SELECT * FROM a INNER JOIN b on a.a_id=b.par ...

  9. 使用 Visual Studio 调试器附加到运行的进程

    为什么调试附加进程? Visual Studio 调试器可以附加到在 Visual Studio 外运行的进程. 可以使用此附加功能执行以下操作: 调试并非在 Visual Studio 中创建的应用 ...

  10. [CF1166C]A Tale of Two Lands题解

    比赛的时候lowerbound用错了 现场WA on test4(好吧我承认我那份代码确实有除了lowerbound以外的问题) 于是只能手动二分 (我好菜啊QAQ 经过一波数学推算,我们发现,设序列 ...