认识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. java 回调的原理与实现

    回调函数,顾名思义,用于回调的函数.回调函数只是一个功能片段,由用户按照回调函数调用约定来实现的一个函数.回调函数是一个工作流的一部分,由工作流来决定函数的调用(回调)时机. 回调原本应该是一个非常简 ...

  2. jQuery学习总结02-属性

    1.attr(name|properties|key,value|fn) 说明:设置和返回被选元素的属性值 示例: 参数: name(属性名称) string properties(作为属性的'名/值 ...

  3. 机器学习-K-means聚类及算法实现(基于R语言)

    K-means聚类 将n个观测点,按一定标准(数据点的相似度),划归到k个聚类(用户划分.产品类别划分等)中. 重要概念:质心 K-means聚类要求的变量是数值变量,方便计算距离. 算法实现 R语言 ...

  4. python if-else替代三元表达式

    python中判断一个数是否是偶数的常规代码: def _compare(data): if data % 2 == 0: return True else: return False # 调用偶数判 ...

  5. python基础--文件的操作

    #r w a 文件读取操作 默认打开为读操作 #f=open('coldplay.txt','r',encoding="utf-8")#open函数默认已系统编码方式打开windo ...

  6. [转]Tomcat9.0安装教程 Tomcat9.0环境变量配置教程

    [转]Tomcat9.0安装教程 Tomcat9.0环境变量配置教程 [转]超详细MySQL安装及基本使用教程

  7. git Octotree:提供项目目录,方便用户在线快速浏览项目结构【转载】

    很好奇的是,GitHub 作为代码托管平台,竟然没有提供项目目录,方便用户在线快速浏览项目结构.所以,在线分析项目源码就会变得很繁琐,必须一层一层点击,然后再一次一次地向上返回.要知道,本来 GitH ...

  8. 如何对Web服务器进行飓风级防御

    万一你的网站被DDOS飓风式攻击,你会怎么办?笔者以经验告诉你,这里的每一层都起着保护网站的作用.如果您宁愿拥有如何在单台服务器上维持大量流量的版本,则可以: 专用硬件服务器,无共享主机 千兆上行链路 ...

  9. centos 6.5 安装 jdk 8

    首先,检查是否已安装jdk,如果有,要先删除 rpm -qa|grep java rpm -e --nodeps filename 然后,从oracle官方网站下载jdk安装包:jdk-8u121-l ...

  10. MyBatis 中的#和$的区别

    #相当于对数据 加上 双引号,$相当于直接显示数据 #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号.如:order by #user_id#,如果传入的值是111,那么解析成sql时的 ...