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

总结:在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. [MIT6.006] 6. AVL Trees, AVL Sort AVL树,AVL排序

    之前第5节课留了个疑问,是关于"时间t被安排进R"的时间复杂度能不能为Ο(log2n)?"和BST时间复杂度Ο(h)的关系.第6节对此继续了深入的探讨.首先我们知道BST ...

  2. 【JVM第一篇--类加载机制】类加载过程

    写在前面的话:本文是在观看尚硅谷JVM教程后,整理的学习笔记.其观看地址如下:尚硅谷2020最新版宋红康JVM教程 一.什么是类加载过程 (1).概述 我们编写的类(.java文件)会被编译器(如ja ...

  3. linux 网络编程 基础

    网络编程基础 套接字编程需要指定套接字地址作为参数,不同的协议族有不同的地址结构,比如以太网其结构为sockaddr_in. 通用套接字: struct sockaddr { sa_family_t ...

  4. SQL SERVER中 DBLINK的实现

    不同服务器数据库之间的数据操作 --创建链接服务器 exec sp_addlinkedserver'ITSV' ,'' , 'SQLOLEDB' ,'远程服务器名或ip地址' exec sp_addl ...

  5. Java解释单链表中的头插法以及尾插法

    单链表属于数据结构中的一种基本结构,是一种线性结构,在此使用Java对其中的头插法以及尾插法进行解释. 首先定义好链表中的节点类: 其中,data代表节点所存放的数据,next代表指向下一节点 对于单 ...

  6. Vue-router插件使用

    单页面原理 Vue是单页面开发,即页面不刷新. 页面不刷新,而又要根据用户选择完成内容的更新该怎么做?Vue中采用锚点来完成. 如访问http://127.0.0.1#/index就是主页,而访问ht ...

  7. 基于物联网的O2O养猪平台

    引言:随着生活水平的提高,人们会越来越重视食品安全问题.在城市里的人想养头猪,并想看着它快快乐乐长大.但是无奈于自己没时间和精力.而农户想养猪,可能又缺少启动资金,且不能承担大的风险.这时候我的美团式 ...

  8. 使用大乌龟git和码云搭建版本库

    刚刚过完清明,上班的第一天,大佬跟我说,要用码云和git搭建一个版本库,菜鸡的博主楞了半天,然后赶紧上网找资料,此时,一旁的大佬已经看不下去了,终于,出手了....... 1. 首先,先把大乌龟git ...

  9. 【appium】appium自动化入门之环境搭建(上)

     第 1 章 环境搭建 1.1 android-sdk 环境 前言 appium可以说是做app 适用最广泛的一个自动化框架,它的主要优势是支持android和ios ,另外脚本语言也是支持 java ...

  10. vue的html2canvas将dom转化为图片时踩得坑

    一.html2canvas中图片涉及跨域图片 应用场景:做个投票活动,将参赛者的信息转化成图片截图分享.用户上传图片上传到腾讯云cos桶中,html2canvas只能转换本地资源的图片,涉及跨域的图片 ...