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

总结:在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. 工具博客转载-ftrace

    https://linux.cn/article-9273-1.html https://lwn.net/Articles/365835/ Documentation/trace/events.txt ...

  2. 线程与更新UI,消除偏见,细谈原理

    前言 相信不少读者都阅读过相类似的文章了,但是我还是想完整的把这之间的关系梳理清楚,细节聊好,希望你也能从中学到一些. 进入正题,大家应该都听过这样一句话--"UI更新要在主线程,子线程更新 ...

  3. cephfs根据存储池显示df容量

    前言 如果用cephfs比较多,应该都知道,在cephfs的客户端进行mount以后,看到的容量显示的是集群的总的容量,也就是你的总的磁盘空间是多少这个地方显示的就是多少 这个一直都是这样显示的,我们 ...

  4. python执行rados命令例子

    前言 我们以前的管理平台在python平台下面做的,内部做的一些操作采用的是命令执行,然后解析的方式去做的,ceph自身有python的rados接口,可以直接调用原生接口,然后直接解析json的方式 ...

  5. Java 实例化接口或抽象类

    1. 实例化接口: 某一天,我们想通过反射调用一个类的方法,但发现方法参数中有一个接口,我们都知道接口不能被实例化,这该怎么办呢? 举例: public class TestLib { public ...

  6. Go原生和GoFrame的Cookie关于MaxAge区别

    Go原生和GoFrame的Cookie关于MaxAge区别 环境: gf v1.14.4 go 1.11 Go原生 type Cookie struct { Name string Value str ...

  7. linux shell简单快捷方式与通配符(元字符)echo -e文本显示颜色

    1.shell常用快捷方式 ^R 搜索历史命令^D 退出^A 光标移动到命令行最前^E 光标移动到命令行最后^L 清屏^U 光标之前删除^K 光标之后删除^Y 撤销^S 锁屏^Q 解锁 2.多条命令执 ...

  8. 【转】AWVS扫描小技巧

    1.文件头加 Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html) 可以绕过狗,waf ...

  9. 攻防世界-Web_php_include (四种解法)

    攻防世界-Web_php_include   (考察的是文件包含) 打开页面是这样一段代码从代码中得知page中带有php://的都会被替换成空 str_replace()以其他字符替换字符串中的一些 ...

  10. 攻克弹唱第七课(如何弹奏neon)

    在本期文章中,笔者将通过Guitar Pro 7来跟大家研究一下neon的曲谱,顺便复习一下之前文章中说过的和弦技巧. 在<如何在指板上寻找特殊和弦(二)>这一期课程中,我们分析过如何使用 ...