Zookeeper---作为服务注册中心
认识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---作为服务注册中心的更多相关文章
- 基于ZooKeeper的服务注册中心
本文介绍基于ZooKeeper的Dubbo服务注册中心的原理. 1.ZooKeeper中的节点 ZooKeeper是一个树形结构的目录服务,支持变更推送,因此非常适合作为Dubbo服务的注册中心. 注 ...
- 使用Spring Cloud搭建服务注册中心
我们在之前的博客中已经介绍过阿里的分布式服务框架dubbo[Linux上安装Zookeeper以及一些注意事项][一个简单的案例带你入门Dubbo分布式框架],但是小伙伴们应该也看到了,阿里的dubb ...
- Dubbo学习笔记1:使用Zookeeper搭建服务治理中心
Zookeeper是Apache Hadoop的子项目,是一个树形的目录服务,支持变更推送,适合作为Dubbo服务的注册中心,工业强度较高,推荐生成环境使用. , 下面结合上图介绍Zookeeper在 ...
- lms框架服务注册中心
服务注册中心原理 在分布式系统里的注册中心.原理是将部署服务的机器地址记录到注册中心,服务消费者在有需求的时候,只需要查询注册中心,输入提供的服务名,就可以得到地址,从而发起调用. 在微服务架构下,主 ...
- silky微服务框架服务注册中心介绍
目录 服务注册中心简介 服务元数据 主机名称(hostName) 服务列表(services) 终结点 时间戳 使用Zookeeper作为服务注册中心 使用Nacos作为服务注册中心 使用Consul ...
- 服务注册中心之ZooKeeper系列(一)
一.服务注册中心介绍 分布式服务框架部署在多台不同的机器上.例如服务A是订单相关的处理服务,服务B是订单的客户的相关信息服务.此时有个需求需要在服务A中获取订单客户的信息.如下图: 此时就面临以下几个 ...
- 服务注册中心Eureka vs Zookeeper vs Consul
前言 在现在云计算和大数据快速发展的今天,业务快速发展和变化.我们以前的单一应用难以应对这种快速的变化, 因此我们需要将以前单一的大应用不断进行差分,分成若干微小的应用或者服务,这就是微服务的思想.但 ...
- 作为服务注册中心,Eureka比Zookeeper好在哪里
CAP是Consistency.Availablity和Partition Tolerance的缩写.一般的分布式系统最多满足其中两条.而Partition Tolerance是分布式系统的关键,因此 ...
- 学习一下 SpringCloud (二)-- 服务注册中心 Eureka、Zookeeper、Consul、Nacos
(1) 相关博文地址: 学习一下 SpringCloud (一)-- 从单体架构到微服务架构.代码拆分(maven 聚合): https://www.cnblogs.com/l-y-h/p/14105 ...
随机推荐
- MyEclipse项目向IDEA项目迁移
1.首先选择File->New->Project from Existing sources/Project form Version Control,如果项目在你的本地则选择 Proje ...
- IntelliJ IDEA 创建spring boot 的Hello World 项目
1.Open IDEA,choose "New-->Project" 2.Choose "Spring Initializr" 3. Choose jav ...
- ReactiveCocoa 之 优雅的 RACCommand
RACCommand 是一个在 ReactiveCocoa 中比较复杂的类,大多数使用 ReactiveCocoa 的人,尤其是初学者并不会经常使用它. 在很多情况下,虽然使用 RACSignal 和 ...
- 1、获取ip地址
1.获取ip地址 System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces() .Select(p => p. ...
- 一、bootstrap-upload
一.bootstrap-upload 前端代码: @{ Layout = null; } <!DOCTYPE html> <html lang="zh-CN"&g ...
- Linux手册页内容
总用9页 man1:可执行程序或shell命令 man2:系统调用(kernel提供的函数) man3:库调用(程序库中的函数) man4:/dev中的特殊文件 ...
- rabbitmq tags
#用户角色####################### RabbitMQ的用户角色分类:none.management.policymaker.monitoring.administrator Ra ...
- cmd获取管理员权限等
鼠标点点点的略过 可输入命令 runas /user:Administrator cmd 或 runas /noprofile /user:Administrator cmd Administrato ...
- 033:DTL常用过滤器(2)
date过滤器: date过滤器:将一个日期按照指定的格式,格式化成字符串.示例代码如下: views.py: from datetime import datetime def cur_date(r ...
- yolo v3 loss=nan, Avg loss=nan的一种原因
我这里是由于数据整理错误导致的,同一标注区域重复2次送入模型,具体如下: 0.798046875 0.5555555555555556 0.04296875 0.03611111111111111 0 ...