SpringCloud学习2-Zookeeper_Consul_Ribbon_OpenFeign

1 Zookeeper服务注册和发现

1、介绍

image-20200711100730926

作用

(1)Zookeeper是一个分布式协调工具,可以实现注册中心功能。

(2)关闭Linux服务器的防火墙后启动Zookeeper服务器。

(3)Zookeeper服务器取代Eureka服务器,Zookeeper作为注册中心。

2、服务提供者cloud-provider-payment8004

1、创建项目

1、项目结构

image-20200817224410715

2、添加yml文件

#8004表示注册到zookeeper服务器的支付服务提供端口号
server:
  port: 8004

#服务别名 --- 注册zookeeper的注册中心名称
#使用下面的39.96.161.64的地址并开通端口号,可以进行服务器的注册
spring:
  application:
    name: cloud-provider-payment
  cloud:
    zookeeper:
      connect-string: 39.96.161.64:2181

3、主启动类

/**
 *  @EnableDiscoveryClient
 *  此时不用添加Eureka
 *  该注解用于向使用consul或者zookeeper作为注册中心时注册服务
 */
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain8004 {
	public static void main(String[] args) {
		SpringApplication.run(PaymentMain8004.class, args);
	}
}

4、Controller

@RestController
@Slf4j
public class PaymentController {

	@Value("${server.port}")
	private String serverPort;

	@GetMapping(value = "/payment/zk")
	public String paymentzk(){
		return "springcloud with zookeeper:"+serverPort+"\t"+ UUID.randomUUID().toString();
	}
}

5、启动阿里云服务器上的zookeeper服务

6、启动cloud-provider-payment8004注册进zookeeper

(1)启动后遇到问题

image-20200817101518444

这是因为我们服务器上使用的zookeeper的版本是3.4.10,而IDEA中导入的依赖中的版本是3.5.3,导致zookeeper版本jar包冲突。

image-20200817225351688

(2)解决方法

 <!-- 只有这个是新的。SpringBoot整合Zookeeper客户端
            jar包冲突报错,jar包的排除和引入
         -->
<!--        <dependency>-->
<!--            <groupId>org.springframework.cloud</groupId>-->
<!--            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>-->
<!--        </dependency>-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
    <!--先排除自身的zk3.5.3-->
    <exclusions>
        <exclusion>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!--再添加zk 3.4.10版本,与服务器的zk一致-->
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.10</version>
</dependency>

7、测试

(1)输入下面的网址:

http://localhost:8004/payment/zk

会在网页上返回一个端口和一串流水号。

(2)获得json串后用在线工具查看。

首先,启动zookeeper服务端后,使用下面的指令启动客户端,进行查看:

./zkCli.sh

通过下面的指令获取服务节点:

ls /

image-20200817225634174

cloud-provider-payment8004节点是临时节点。

3、服务消费者cloud-consumerzk-order80

1、创建项目

1、项目结构

image-20200817230023634

2、添加yml文件

server:
  port: 80

spring:
  application:
    name: cloud-consumer-order
  cloud:
    #注册到zookeeper中的地址
    zookeeper:
      connect-string: 39.96.161.64:2181

3、启动类

@SpringBootApplication
@EnableDiscoveryClient
public class OrderZKMain80 {
	public static void main(String[] args) {
		SpringApplication.run(OrderZKMain80.class,args);
	}
}

4、业务类

(1)配置Bean

@Configuration
public class ApplicationContextConfig {

	@LoadBalanced
	@Bean
	public RestTemplate getRestTemplate() {
		return new RestTemplate();
	}
}

(2)controller

@RestController
@Slf4j
public class OrderZKController {

	public static final String INVOME_URL = "http://cloud-provider-payment";

	@Resource
	private RestTemplate restTemplate;

	@GetMapping("/consumer/payment/zk")
	public String payment (){
		String result = restTemplate.getForObject(INVOME_URL+"/payment/zk",String.class);
		return result;
	}
}

5、启动cloud-consumerzk-order80注册进zookeeper

6、测试

​ 此时,在环境中有cloud-provider-payment8004cloud-consumerzk-order80同时运行。

(1)查看阿里云服务器的zookeeper的节点

image-20200817230538582

(2)输入网址:

http://localhost:8004/payment/zk

会在网页上返回一个端口和一串流水号。

image-20200817231032580

(3)输入网址:

http://localhost/consumer/payment/zk

image-20200817231502460

2 Consul服务注册和发现

1、介绍

1、网址

介绍网址:

https://www.consul.io/intro/index.html

下载网址:

https://www.consul.io/downloads.html

image-20200817231701528

2、作用

(1)服务发现:提供HTTP和DNS两种发现方式。

(2)健康监测:支持多种协议,HTTP、TCP、Docker、Shell脚本定制化。

(3)KV存储:key , Value的存储方式。

(4)多数据中心:Consul支持多数据中心。

(5)可视化Web界面。

2、安装并运行Consul

1、下载完成后只有一个consul.exe文件,硬盘路径下双击运行,使用下面的指令查看版本信息。

consul --version

image-20200817232019096

2、使用开发模式启动

(1)使用下面的指令启动consul:

consul agent -dev

(2)通过以下地址可以访问Consul的首页:

http://localhost:8500

(3)结果页面

image-20200817232215825

3、服务提供者cloud-providerconsul-payment8006

1、创建项目

1、项目结构

image-20200817232337382

2、添加yml文件

#consul服务端口号
server:
  port: 8006

spring:
  application:
    name: consul-provider-payment
#consul 注册中心地址
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}

3、主启动类

@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain8006 {
   public static void main(String[] args) {
      SpringApplication.run(PaymentMain8006.class,args);
   }
}

4、业务类controller

@RestController
@Slf4j
public class PaymentController {

   @Value("${server.port}")
   private String serverPort;

   @GetMapping(value = "/payment/consul")
   public String paymentConsul() {
      return "springcloud with consul: " + serverPort + "\t" + UUID.randomUUID().toString();
   }
}

5、测试

​ 输入网址:

http://localhost:8006/payment/consul

将会有一个端口号+ 一串流水号;输入网址:

http://localhost:8500

将会弹出下面的界面:

image-20200817232546649

4、服务消费者cloud-consumerconsul-order80

1、创建项目

1、项目结构

image-20200817232737391

2、添加yml文件

server:
  port: 80

spring:
  application:
    name: consul-consumer-order
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}

3、主启动类

@SpringBootApplication
@EnableDiscoveryClient
public class OrderConsulMain80 {
   public static void main(String[] args) {
      SpringApplication.run(OrderConsulMain80.class,args);
   }
}

4、业务类

(1)配置Bean

@Configuration
public class ApplicationContextConfig {

   @LoadBalanced
   @Bean
   public RestTemplate getRestTemplate(){
      return new RestTemplate();
   }

}

(2)controller

@RestController
@Slf4j
public class OrderConsulController {
	public static final String INVOME_URL = "http://consul-provider-payment";
	@Resource
	private RestTemplate restTemplate;

	@GetMapping("/consumer/payment/consul")
	public String payment() {
		String result = restTemplate.getForObject(INVOME_URL + "/payment/consul", String.class);
		return result;
	}
}

5、测试

(1)输入网址:

http://localhost:8500

将会弹出下面的界面:

image-20200817233015020

(2)输入网址:http://localhost/consumer/payment/consul,将会获得

cloud-providerconsul-payment8006的端口号+一串流水号。

5、三个注册中心的异同点

1、CAP

(1)C:Consistency(强一致性)

(2)A:Availability(可用性)

(3)P:Partition tolerance(分区容错)

CAP理论关注粒度是数据,而不是整体系统设计的策略。

2、分析

image-20200817233733267

image-20200817234843232

组件名语言CAP服务器健康检查对外保留接口SpringBoot集成
EurekaJavaAP可配支持HTTP已集成
ConsulGoCP支持HTTP/DNS已集成
ZookeeperJavaCP支持客户端已集成

(1)AP(Eureka)

image-20200817233600030

image-20200817233607656

(2)CP(Zookeeper/Consul)

image-20200817233634551

image-20200817233647176

3 Ribbon负载均衡服务调用

1、介绍

image-20200820083732769

1、官网资料

网址:https://github.com/Netflix/ribbon/wiki/Getting-Started

目前Ribbon也进入维护阶段:

image-20200820083848170

替代方案:

image-20200820084009441

2、作用

(1)负载均衡

image-20200820084102765

(a)集中式LB

image-20200820084157828

(b)进程式LB

image-20200820084240600

(2)总结

负载均衡+RestTemplate调用(80通过轮询负载访问8001/8002)。

2、负载均衡演示

1、架构说明

​ Ribbon其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例。

image-20200820084959642

image-20200820085017075

2、pom文件

image-20200820085338979

image-20200820085351457

3、RestTemplate的使用

(1)官网

https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html

image-20200820085727229

(2)getForObject方法/getForEntity方法

image-20200820085745989

(3)postForObject/postForEntity

image-20200820085833394

3、Ribbon核心组件IRule

1、根据特定算法从服务列表中选取一个要访问的服务。

image-20200820090333139

image-20200820090348766

2、如何替换

(1)修改cloud-consumer-order80模块

配置细节:

image-20200820102909584

image-20200820102929250

(2)新建package-com.xiaolun.myrule

image-20200820103023940

(3)添加规则类

@Configuration
public class MySelfRule {

    @Bean
    public IRule myRule(){
        return new RandomRule();//定义为随机
    }
}

(4)主启动类添加注解@RibbonClient

@EnableEurekaClient
@SpringBootApplication
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class,args);
    }

}

(5)测试

输入网址:

http://localhost/consumer/payment/get/5

可以随机访问。

4、手写负载均衡算法

1、原理

image-20200820103408449

2、手写算法

(1)启动cloud-eureka-Server-7001/7002。

(2)改造cloud-provider-payment8001/8002

//controller中添加下面的内容,当消费者访问时,可以将端口号返回
@GetMapping(value = "/payment/lb")
    public String getPaymentLB() {
    return serverPort;
}

(3)改造cloud-consumer-order80

(a)ApplicationContextBean去掉@LoadBalanced,主要是使用自己写的负载均衡。

(b)创建LoadBalancer接口

image-20200820104857726

public interface LoadBalancer {
	//收集服务器总共有多少台能够提供服务的机器,并放到list里面
	ServiceInstance instances(List<ServiceInstance> serviceInstances);

}

(c)LoadBalancer接口实现类

@Component
public class MyLB implements LoadBalancer {

	private AtomicInteger atomicInteger = new AtomicInteger(0);

	//坐标
	private final int getAndIncrement() {
		int current;
		int next;
		do {
			current = this.atomicInteger.get();
			next = current >= 2147483647 ? 0 : current + 1;
		} while (!this.atomicInteger.compareAndSet(current, next));  //第一个参数是期望值,第二个参数是修改值
		System.out.println("*******第几次访问,次数next: " + next);
		return next;
	}

	@Override
	public ServiceInstance instances(List<ServiceInstance> serviceInstances) {  //得到机器的列表
		int index = getAndIncrement() % serviceInstances.size(); //得到服务器的下标位置
		return serviceInstances.get(index);
	}
}

(d)改造controller

@Resource
private LoadBalancer loadBalancer;

@Resource
private DiscoveryClient discoveryClient;

@GetMapping(value = "/consumer/payment/lb")
	public String getPaymentLB() {
		List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
		if (instances == null || instances.size() <= 0) {
			return null;
		}
		ServiceInstance serviceInstance = loadBalancer.instances(instances);
		URI uri = serviceInstance.getUri();
		log.info("uri-----"+uri);
		return restTemplate.getForObject(uri + "/payment/lb", String.class);
	}

(e)测试

输入网址:

http://localhost/consumer/payment/lb

浏览器输出:

image-20200820105142930

端口8001/8002可以交替变换,即实现了负载均衡。

5 OpenFeign服务接口调用

1、介绍

1、概述

image-20200820105358611

Feign是一个声明式的web服务客户端,让编写web服务客户端变得非常容易,只需创建一个接口并在接口上添加注解即可。

GitHub:

https://github.com/spring-cloud/spring-cloud-openfeign

2、作用

image-20200820105421099

3、Feign和OpenFeign的区别

image-20200820105522759

2、OpenFeign使用步骤

核心:接口+注解:微服务调用接口+@FeignClient。

项目结构:

image-20200820112843704

1、新建cloud-consumer-feign-order80,Feign在消费端使用。

2、添加pom文件

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

3、添加yml文件

server:
  port: 80

spring:
  application:
    name: cloud-order-service
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka

4、添加主启动类

@SpringBootApplication
@EnableFeignClients //添加该注解
@EnableEurekaClient
public class OrderFeignMain80 {
	public static void main(String[] args) {
		SpringApplication.run(OrderFeignMain80.class, args);
	}
}

5、添加业务类

实现:业务逻辑接口+@FeignClient配置调用provider服务。

(1)新建PaymentFeignService接口并新增注解@FeignClient

@Component
//CLOUD-PAYMENT-SERVICE服务的的名字
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {
	@GetMapping("/payment/get/{id}")
	public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
}

注解@FeignClient是一个使用的标识,在启动类的注解@EnableFeignClients是一个启用标识。

(2)添加controller

@RestController
public class OrderFeignController {

	@Resource
	private PaymentFeignService paymentFeignService;

	@GetMapping(value = "/consumer/payment/get/{id}")
	public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
		return paymentFeignService.getPaymentById(id);
	}
}

5、测试

先启动2个eureka集群cloud-eureka-Server7001/7002,再启动2个微服务cloud-provider-payment8001/8002,最后启动cloud-consumer-feign-order80启动,输入地址:

http://localhost/consumer/payment/get/5

image-20200820113647003

可以发现Feign自带负载均衡配置项,上图中的端口号8001/8002来回切换。

执行逻辑:

cloud-consumer-feign-order80模块此时作为消费者,当客户端输入地址后,地址首先会进入到cloud-consumer-feign-order80模块中controller中,即OrderFeignController的方法,执行完成后,该方法会到接口类PaymentFeignService中执行@GetMapping的方法,这样通过OpenFeign就可以调用cloud-provider-payment8001/8002,即消费者到服务者之间的网路就打通了。

image-20200820114749976

3、超时控制

1、案例

(1)在服务提供方cloud-provider-payment8001/8002中的com.xiaolun.springcloud.controller中添加延时程序:

@GetMapping(value = "/payment/feign/timeout")
public String paymentFeignTimeout() {
   try {
      TimeUnit.SECONDS.sleep(2);
   } catch (Exception e) {
      e.printStackTrace();
   }
   return serverPort;
}

(2)服务消费方cloud-consumer-feign-order80的接口com.xiaolun.service.PaymentFeignService中添加超时方法PaymentFeignService(和(1)中的方法对应)

@GetMapping(value = "/payment/feign/timeout")
	public String paymentFeignTimeout();

(3)服务消费方cloud-consumer-feign-order80的控制类com.xiaolun.controller.OrderFeignController中添加超时方法PaymentFeignService

@GetMapping(value = "/consumer/payment/feign/timeout")
public String paymentFeignTimeout(){
	return paymentFeignService.paymentFeignTimeout();
}

(4)测试

​ 先启动2个eureka集群cloud-eureka-Server7001/7002,再启动2个微服务cloud-provider-payment8001/8002,最后启动cloud-consumer-feign-order80启动,输入地址:

http://localhost/consumer/payment/feign/timeout

会有下面的错误界面:

image-20200820144238384

2、超时问题的解决

image-20200820143336511

​ 所以,我们需要在yml文件中开启超时的配置信息。因为OpenFeign默认支持Ribbon,如下图所示:

image-20200820144338334

​ 我们只需要在yml文件中添加如下的配置即可开启OpenFeign客户端超时控制:

#设置feign客户端超时时间(OpenFeign默认支持ribbon)
ribbon:
  #指的是建立连接后从服务器读取可用资源所用的时间
  ReadTimeout:  5000
  #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接时间
  ConnectTimeout: 5000

注:当我们只在cloud-provider-payment8001中添加方法时,而未在cloud-provider-payment8002中添加超时方式法,由于cloud-consumer-feign-order80会轮询的访问服务提供者,所以,在访问的过程中,有一次会出错。

4、日志打印

1、介绍

image-20200820144702027

日志级别:

image-20200820144732569

2、日志打印的配置

(1)目录结构

image-20200820144823293

(2)在com.xiaolun.config下配置日志bean

@Configuration
public class FeignConfig {

   @Bean
   Logger.Level feignLoggerLevel(){
      //代表自己开启的是一个详细日志
      return Logger.Level.FULL;
   }
}

(3)在yml文件中开启日志的Feign客户端

logging:
  level:
    #feign日志以debug级别监控下面这个接口,并打印出全部日志信息
    com.xiaolun.service.PaymentFeignService: debug

(4)后台日志查看

image-20200820145032605

原文地址:https://blog.csdn.net/weixin_43334389/article/details/114011017

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Nacos 中的参数有很多,如:命名空间、分组名、服务名、保护阈值、服务路由类型、临时实例等,那这些参数都是什么意思?又该如何设置?接下来我们一起来盘它。 1.命名空间 在 Nacos 中通过命名空间(Namespace)+ 分组(Group)+服务名(Name)可以定位到一个唯一的服务实例。 命名
Nacos 支持两种 HTTP 服务请求,一个是 REST Template,另一个是 Feign Client。之前的文章咱们介绍过 Rest Template 的调用方式,主要是通过 Ribbon(负载均衡) + RestTemplate 实现 HTTP 服务调用的,请求的核心代码是这样的: @
Nacos 是 Spring Cloud Alibaba 中一个重要的组成部分,它提供了两个重要的功能:服务注册与发现和统一的配置中心功能。 服务注册与发现功能解决了微服务集群中,调用者和服务提供者连接管理和请求转发的功能,让程序的开发者无需过多的关注服务提供者的稳定性和健康程度以及调用地址,因为这
Spring Cloud Alibaba 是阿里巴巴提供的一站式微服务开发解决方案,目前已被 Spring Cloud 官方收录。而 Nacos 作为 Spring Cloud Alibaba 的核心组件之一,提供了两个非常重要的功能:服务注册中心(服务注册和发现)功能,和统一配置中心功能。 Nac
在 Nacos 的路由策略中有 3 个比较重要的内容:权重、保护阈值和就近访问。因为这 3 个内容都是彼此独立的,所以今天我们就单独拎出“保护阈值”来详细聊聊。 保护阈值 保护阈值(ProtectThreshold):为了防止因过多实例故障,导致所有流量全部流入剩余健康实例,继而造成流量压力将剩余健
前两天遇到了一个问题,Nacos 中的永久服务删除不了,折腾了一番,最后还是顺利解决了。以下是原因分析和解决方案,建议先收藏,以备不时之需。 临时实例和持久化实例是 Nacos 1.0.0 中新增了一个特性。临时实例和持久化实例最大的区别是健康检查的方式:临时实例使用客户端主动上报的健康检查模式,而
Spring Cloud Alibaba 技术体系中的 Nacos,提供了两个重要的功能:注册中心(服务注册与发现)功能和配置中心功能。 其中注册中心解决了微服务调用中,服务提供者和服务调用者的解耦,让程序开发者可以无需过多的关注服务提供者和调用者的运行细节,只需要通过 Nacos 的注册中心就可以
负载均衡通器常有两种实现手段,一种是服务端负载均衡器,另一种是客户端负载均衡器,而我们今天的主角 Ribbon 就属于后者——客户端负载均衡器。 服务端负载均衡器的问题是,它提供了更强的流量控制权,但无法满足不同的消费者希望使用不同负载均衡策略的需求,而使用不同负载均衡策略的场景确实是存在的,所以客
本篇文章为大家展示了如何解决Spring Cloud 服务冲突问题,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。一、背景...
本篇内容主要讲解“spring cloud服务的注册与发现怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“spri...
本篇内容介绍了“Dubbo怎么实现Spring Cloud服务治理 ”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处...
本篇内容主要讲解“SpringCloud相关面试题有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringCloud相...
如何分析Spring Cloud Ribbon、Spring Cloud Feign以及断路器,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希
这篇文章主要讲解了“springcloud微服务的组成部分有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“s...
这篇文章主要讲解了“SpringCloud的OpenFeign项目怎么创建”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习...
本篇内容主要讲解“spring cloud oauth3整合JWT后获取用户信息不全怎么办”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带...
怎样解析微服务架构SpringCloud,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。...
这篇文章主要介绍spring cloud中API网关的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、服务网关简介1、外观模式客户端...
本篇内容介绍了“Spring Cloud微服务的相关问题有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处...
本文小编为大家详细介绍“spring cloud config整合gitlab如何搭建分布式的配置中心”,内容详细,步骤清晰,细节处理妥当,希望这篇“spring cloud config整合gi...