接下来在整个微服务架构中,我们比较关心的就是服务间的服务改如何调用,有哪些调用方式?

总结:在springcloud中服务间调用方式主要是使用 http restful方式进行服务间调用

1. 基于RestTemplate的服务调用

在上面的基础上,使用的是consul注册,pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent> <groupId>com.md</groupId>
<artifactId>04-products9998</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>04-products9998</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <!--引入consul依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency> <!-- 这个包是用做健康度监控的-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency> </dependencies> <!--全局管理springcloud版本,并不会引入具体依赖-->
<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> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

1. 说明

  • spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。

2. RestTemplate 服务调用

  1. 创建两个服务并注册到consul注册中心中
  • users 代表用户服务 端口为 9999
  • products 代表商品服务 端口为 9998

    `注意:这里服务仅仅用来测试,没有实际业务意义



3. 在商品服务中提供服务方法

@RestController
@Slf4j
public class ProductController {
@Value("${server.port}")
private int port;
@GetMapping("/product/findAll")
public Map<String,Object> findAll(){
log.info("商品服务查询所有调用成功,当前服务端口:[{}]",port);
Map<String, Object> map = new HashMap<String,Object>();
map.put("msg","服务调用成功,服务提供端口为: "+port);
map.put("status",true);
return map;
}
}

4. 在用户服务中使用restTemplate进行调用

@RestController
@Slf4j
public class UserController {
@GetMapping("/user/findAll")
public String findAll(){
log.info("调用用户服务...");
//1. 使用restTemplate调用商品服务
RestTemplate restTemplate = new RestTemplate();
// get请求getxxx,post请求postxxx
// 参数1:请求路径,参数2:返回的类型是String的
String forObject = restTemplate.getForObject("http://localhost:9998/product/findAll",
String.class);
return forObject;
}
}

5. 启动服务



6. 测试服务调用

7. 总结

  • rest Template是直接基于服务地址调用没有在服务注册中心获取服务,也没有办法完成服务的负载均衡如果需要实现服务的负载均衡需要自己书写服务负载均衡策略。

    restTemplate直接调用存在问题
  • 1.直接使用restTemplate方式调用没有经过服务注册中心获取服务地址,代码写死不利于维护,当服务宕机时不能高效剔除
  • 2.调用服务时没有负载均衡需要自己实现负载均衡策略

2. 基于Ribbon的服务调用

0. 说明

  • 官方网址: https://github.com/Netflix/ribbon
  • Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。

再创建一个服务类,和上面的服务类一样,只有端口不同

server.port=9997
spring.application.name=products
spring.cloud.consul.port=8500
spring.cloud.consul.host=localhost

其他一样

@RestController
@Slf4j
public class ProductController {
@Value("${server.port}")
private int port;
@GetMapping("/product/findAll")
public Map<String,Object> findAll(){
log.info("商品服务查询所有调用成功,当前服务端口:[{}]",port);
Map<String, Object> map = new HashMap<String,Object>();
map.put("msg","服务调用成功,服务提供端口为: "+port);
map.put("status",true);
return map;
}
}

1. Ribbon 服务调用

# 1.项目中引入依赖
- 说明:
1.如果使用的是eureka client 和 consul client,无须引入依赖,因为在eureka,consul中默认集成了ribbon组件
2.如果使用的client中没有ribbon依赖需要显式引入如下依赖
<!--引入ribbon依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
# 2.查看consul client中依赖的ribbon

# 3.使用restTemplate + ribbon进行服务调用
- 使用discovery client 进行客户端调用
- 使用loadBalanceClient 进行客户端调用
- 使用@loadBalanced 进行客户端调用
# 3.1 使用discovery Client形式调用
@Autowired
private DiscoveryClient discoveryClient; //获取服务列表,返回全部的,服务id,上面的products
List<ServiceInstance> products = discoveryClient.getInstances("服务ID");
for (ServiceInstance product : products) {
log.info("服务主机:[{}]",product.getHost());
log.info("服务端口:[{}]",product.getPort());
log.info("服务地址:[{}]",product.getUri());
log.info("====================================");
}
# 3.2 使用loadBalance Client形式调用
@Autowired
private LoadBalancerClient loadBalancerClient;
//根据负载均衡策略选取某一个服务调用,服务id=products
ServiceInstance product = loadBalancerClient.choose("服务ID");//地址 默认轮询策略
log.info("服务主机:[{}]",product.getHost());
log.info("服务端口:[{}]",product.getPort());
log.info("服务地址:[{}]",product.getUri());
# 3.3 使用@loadBalanced(常用)
//1.整合restTemplate + ribbon
@Configuration
public class RestTemplateConfig { // 在工厂中创建一个restTemplate对象
@Bean
// 加上这个注解代表当前的restTemplate对象带有ribbon负载均衡
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
} //2.调用controller服务位置注入RestTemplate
// 此时的restTemplate就具有了负载均衡的功能
@Autowired
private RestTemplate restTemplate; //3.调用
@RestController
@Slf4j
public class UserController {
@Autowired
private RestTemplate restTemplate; @GetMapping("/user/findAll")
public String findAll(){
// 服务id就是在配置文件中的当前服务名products
String forObject = restTemplate.getForObject("http://服务ID/product/findAll",
String.class);
return forObject;
}
}

默认的轮训策略,也就是当前访问的9998,之后是9997,循环访问

2. Ribbon负载均衡策略

ribbon负载均衡算法

  • RoundRobinRule 轮训策略 按顺序循环选择 Server

  • RandomRule 随机策略 随机选择 Server

  • AvailabilityFilteringRule 可用过滤策略

    `会先过滤由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问

  • WeightedResponseTimeRule 响应时间加权策略

    `根据平均响应的时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高,刚启动时如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够会切换到

  • RetryRule 重试策略

    `先按照RoundRobinRule的策略获取服务,如果获取失败则在制定时间内进行重试,获取可用的服务。

  • BestAviableRule 最低并发策略

    `会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务

3.修改服务的默认负载均衡策略

# 1.修改服务默认随机策略
- 服务id.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
`下面的products为服务的唯一标识
products.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

4.Ribbon停止维护

# 1.官方停止维护说明
- https://github.com/Netflix/ribbon

SpringCloud-服务间通信方式的更多相关文章

  1. SpringCloud服务间调用

    SpringCloud服务间的调用有两种方式:RestTemplate和FeignClient.不管是什么方式,他都是通过REST接口调用服务的http接口,参数和结果默认都是通过jackson序列化 ...

  2. SpringCloud 服务间互相调用 @FeignClient注解

    SpringCloud搭建各种微服务之后,服务间通常存在相互调用的需求,SpringCloud提供了@FeignClient 注解非常优雅的解决了这个问题 首先,保证几个服务都在一个Eureka中注册 ...

  3. 【微服务落地】服务间通信方式: gRPC的入门

    gRPC是什么 官方介绍: https://grpc.io/docs/what-is-grpc/introduction/ "A high-performance, open-source ...

  4. SpringCloud --服务调用Feign

    介绍 服务间通信简介 一个系统可以由不同的微服务构成,比如一个电商系统可以由订单服务.商品服务.用户服务等共同组成. 这些服务相互独立,但又相互依赖.由于它们相互依赖,所以需要通过通信的方式来进行相互 ...

  5. SpringCloud使用Feign实现服务间通信

    SpringCloud的服务间通信主要有两种办法,一种是使用Spring自带的RestTemplate,另一种是使用Feign,这里主要介绍后者的通信方式. 整个实例一共用到了四个项目,一个Eurek ...

  6. SpringCloud实现服务间调用(RestTemplate方式)

    上一篇文章<SpringCloud搭建注册中心与服务注册>介绍了注册中心的搭建和服务的注册,本文将介绍下服务消费者调用服务提供者的过程. 本文目录 一.服务调用流程二.服务提供者三.服务消 ...

  7. 小D课堂 - 新版本微服务springcloud+Docker教程_4-04 高级篇幅之服务间调用之负载均衡策略调整实战

    笔记 4.高级篇幅之服务间调用之负载均衡策略调整实战     简介:实战调整默认负载均衡策略实战 自定义负载均衡策略:http://cloud.spring.io/spring-cloud-stati ...

  8. ②SpringCloud 实战:引入Feign组件,完善服务间调用

    这是SpringCloud实战系列中第二篇文章,了解前面第一篇文章更有助于更好理解本文内容: ①SpringCloud 实战:引入Eureka组件,完善服务治理 简介 Feign 是一个声明式的 RE ...

  9. SpringCloud微服务服务间调用之OpenFeign介绍

    开发微服务,免不了需要服务间调用.Spring Cloud框架提供了RestTemplate和FeignClient两个方式完成服务间调用,本文简要介绍如何使用OpenFeign完成服务间调用. Op ...

  10. SpringCloud初体验:三、Feign 服务间调用(FeignClient)、负载均衡(Ribbon)、容错/降级处理(Hystrix)

    FeignOpenFeign Feign是一种声明式.模板化的HTTP客户端. 看了解释过后,可以理解为他是一种 客户端 配置实现的策略,它实现 服务间调用(FeignClient).负载均衡(Rib ...

随机推荐

  1. UnixIPC之共享内存

    Unix-IPC之共享内存 一,共享内存的概念 共享内存通信技术是一种最快的可用IPC形式,它是针对其他通信机制运行效率低和设计的新型通信技术(其他的如:信号量,管道,套接字等).这种通信技术往往与其 ...

  2. UNP——第四章,TCP套接字编程

    1.socket 函数 首先被调用的函数,用于选择通信协议. socket调用成功后,得到的套接字为主动套接字CLOSED状态. PF 和 AF 的关系 PF的是协议族,AF是地址族,理论上一个PF包 ...

  3. 如何开发一个maven插件

    maven是当下最流行的项目管理工具,其丰富的插件为我们的工作带来了很大的便利. 但是在一些情况下,开源的插件并不能完全满足我们的需求,我们需要自己创建插件,本文就从0开始带大家一起创建自己的插件. ...

  4. parted命令采用gpt分区过程

    Gpt无分区限制,故只有主分区,无扩展分区和逻辑分区.分区直接按容量算,不按柱面算. 查看分区:parted -l 将分区表类型转换为gpt.: 主要命令mklabel gpt 对sdc盘分区: [r ...

  5. 协程实现socket并发编程

    在python中多线程其实是被弱化了,因为由于GIL的原因,同一时间只有一个线程能访问CPU,即使你的CPU是多核的在python中因为多线程被弱化了,所以协程显的重要,能够在一个线程中提高CPU的利 ...

  6. css子选择器 :frist-child :nth-child(n) :nth-of-type(n) ::select选择器

    记录一下前一段时间使用.学习的几种选择器. 1. :frist-child 选择器n 比如<ul><li></li> <li></li> & ...

  7. [LeetCode题解]109. 有序链表转换二叉搜索树 | 快慢指针 + 递归

    题目描述 给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. 示例: 给定的有序链表: ...

  8. ubuntu16.04搭建LAMP(独立安装)

    修改APT源 备份原文件source.list sudo cp /etc/source.list /etc/source.list.bak 修改source.list sudo vi /etc/sou ...

  9. FL Studio钢琴卷轴之刷子工具以及其他

    上一篇文章我们重点讲解了FL Studio钢琴卷轴的画笔工具,今天我们就来讲解钢琴卷轴窗口中剩下的工具.由于接下来的工具都很简单,所以我们将放在一起讲,现在就和小编一起来看看FL Studio钢琴卷轴 ...

  10. 推荐一款比迅雷下载速度快的mac下载器

    Folx和迅雷是2款支持在Mac系统上进行文件资源下载的工具,两者都支持BT种子资源的下载和直链下载,但Folx还另外支持了下载计划的自定义和智能限速功能.本文主要是为了比较Folx和迅雷在下载同一资 ...