SpringCloud之服务调用
1.Ribbon
1.1负载均衡LB
全称Load Balance,将用户的请求平摊到多个服务器上,从而达到系统的HA。
集中式LB:在服务消费者和服务提供者之间使用独立的LB设施,如硬件,由该设施负责把访问请求通过某种策略转发至服务提供方。
进程内LB:将LB逻辑继承到服务消费者,消费者从服务注册中心获知有哪些地址可用,然后从这些地址中选择一个合适的来使用。Ribbon属于进程内LB。
1.2Ribbon定义
基于NetFlix Ribbon实现的一套客户端负载均衡的工具。
1.3项目开发
源代码:https://github.com/zhongyushi-git/springcloud-ribbon.git
1)创建TestTemplate模块以及Eureka服务器集群。具体步骤可参考https://www.cnblogs.com/zys2019/p/12636241.html#_label0。可直接下载代码,在此代码基础上修改。
2)在cloud-consumer80中添加eureka依赖
<!--eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
不需要引入ribbon依赖,原因是在eureka中已经引入了。
3)修改cloud-consumer80的配置文件yml,配置eureka
#把客户端注册到服务列表中
eureka:
client:
#表示是否将自己注册进EurekaServer默认为true
register-with-eureka: false
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka/, http://eureka7002.com:7002/eureka/, http://eureka7003.com:7003/eureka/
4)在cloud-consumer80的ConfigBean类添加@LoadBalance注解
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
5)主启动类添加@EnableEurekaClient
@SpringBootApplication
@EnableEurekaClient
public class ConsumerMain80 {
public static void main(String[] args) {
SpringApplication.run(ConsumerMain80.class, args);
}
}
6)修改Usercontroller类中访问的基本路径BASE_URL为微服务名
private final String BASE_URL="http://CLOUD-PROVIDER";
7)运行测试
先分别启动7001,7002,7003,然后启动8001和80。
使用postman工具输入http://127.0.0.1/consumer/get/1使用get方式测试,再输入http://127.0.0.1/consumer/add?name=嘻哈哈&phone=101使用post方式测试。
1.4Ribbon负载均衡配置
1)创建服务提供者集群cloud-provider8002,cloud-provider8003,然后按照8001的配置直接复制到8002和8003
2)创建对应的数据库db2021和bd2022
create database db2021;
use db2021;
create table user (
id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
name varchar(200) DEFAULT '',
phone varchar(200) DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; insert into user values(null,'李明','102');
insert into user values(null,'赵慧','102');
insert into user values(null,'李凯','102'); create database db2022;
use db2022;
create table user (
id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
name varchar(200) DEFAULT '',
phone varchar(200) DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; insert into user values(null,'李明','103');
insert into user values(null,'赵慧','103');
insert into user values(null,'李凯','103');
不同的数据库表根据phone字段区分不同的库。
3)修改8002和8003的yml,包括端口号、数据库名和实例id。应用程序的名字一定不要改,要保持一致。
4)先启动eureka集群,然后启动微服务提供者集群,最后启动微服务消费者。
5)访问http://localhost/consumer/get/1,刷新几次会发现查询的是不同的数据库数据。
由此可以看出ribbon是对服务提供者进行负载均衡。
1.5Ribbon负载均衡策略
1.5.1策略
Ribbon的核心组件是IRule,它的作用就是根据特定的算法从服务列表中选择一个要访问的服务。
| 策略 | 描述 |
| RandomRule | 随机 |
| RoundRobinRule | 轮询,按照顺序选择server,是Ribbon默认的策略 |
| RetryRule | 重试,在一个配置时间段内,当选择server不成功,则一直尝试选择一个可用的server |
| BestAvailableRule | 最低并发,逐个考察server,如果server断路器打开,则忽略,再选择其中并发链接最低的server |
| AvailabilityFilteringRule | 可用过滤,过滤掉一直失败并被标记为circuit tripped的server,过滤掉那些高并发链接的server |
| ResponseTimeWeightedRule | 响应时间加权重,根据server的响应时间分配权重,响应时间越长,权重越低,被选择到的概率也就越低。 |
| ZoneAvoidanceRule | 区域权重,综合判断server所在区域的性能和server的可用性,轮询选择server并且判断一个AWS Zone的运行性能是否可用,剔除不可用的Zone中的所有server |
1.5.2切换默认的策略
在服务消费者中config包的配置类添加
//切换默认的策略
@Bean
public IRule myRule(){
return new RandomRule();
}
1.5.3自定义策略
在消费者中新建包com.zys.rule,新建配置类MySelfRule
package com.zys.rule; import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; @Configuration
public class MySelfRule { @Bean
public IRule myRule(){
return new MyRandomRule();
}
}
新建策略类MyRandomRule
package com.zys.rule; import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server; import java.awt.*;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom; /**
* 自定义轮询规则,每执行5次再切换下一个服务器
*/ public class MyRandomRule extends AbstractLoadBalancerRule { private int total = 0;
private int currentIndex = 0; public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
}
Server server = null; while (server == null) {
if (Thread.interrupted()) {
return null;
}
List<Server> upList = lb.getReachableServers();
List<Server> allList = lb.getAllServers(); int serverCount = allList.size();
if (serverCount == 0) {
/*
* No servers. End regardless of pass, because subsequent passes
* only get more restrictive.
*/
return null;
}
if (total < 5) {
server = upList.get(currentIndex);
total++;
} else {
total = 0;
currentIndex++;
if (currentIndex >= upList.size()) {
currentIndex = 0;
}
}
if (server == null) {
/*
* The only time this should happen is if the server list were
* somehow trimmed. This is a transient condition. Retry after
* yielding.
*/
Thread.yield();
continue;
} if (server.isAlive()) {
return (server);
} // Shouldn't actually happen.. but must be transient or a bug.
server = null;
Thread.yield();
} return server; } @Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
} @Override
public void initWithNiwsConfig(IClientConfig iClientConfig) { }
}
重新启动消费者,每刷新5次才会切换下一个服务器。
2.OpenFeign
2.1定义
在ribbon中,使用微服务名和RestTemolate的方式进行服务的调用,而feign是一个声明式的Web服务客户端,是面向接口编程的。也就是说使用Feign,只需要创建一个接口并使用注解方式配置它,就可以完成对微服务提供方的接口绑定。openfeign对feign进行进一步的封装,添加了springmvc的一些功能,更加强大。
2.2项目开发
源代码:https://github.com/zhongyushi-git/cloud-feign.git
1)在ribbon的基础上,按照消费者创建模块cloud-feign-consumer80,然后删除之前的消费者模块
2)在cloud-feign-consumer80的pom中导入依赖
<!--feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
3)创建接口UserClientService
新建包com.zys.cloud.service,在包下新建接口并添加注解@FeiginClient,指定微服务的名称
package com.zys.cloud.service; import com.zys.cloud.entity.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; //添加注解,指定微服务名称
@FeignClient(value="CLOUD-PROVIDER")
public interface UserClientService { @GetMapping("/user/get/{id}")
public User getUser(@PathVariable("id")long id); @PostMapping("/user/add")
int addUser(User user);
}
4)在controller中注入UserClientService接口
修改调用的方法,使用service的方式调用服务
@Resource
private UserClientService userClientService; @GetMapping("/get/{id}")
public User getUser(@PathVariable("id") long id){
return userClientService.getUser(id);
} @PostMapping("/add")
public int addUser(User user){
return userClientService.addUser(user);
}
5)在启动类上添加注解@EnableFeignClients
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class ConsumerFeignMain80 {
public static void main(String[] args) {
SpringApplication.run(ConsumerFeignMain80.class, args);
}
}
7)删除config包,如果没有就不删除。
8)启动测试
先启动eureka集群,然后启动服务提供者集群,再启动服务消费者,在浏览器输入http://localhost://consumer/get/3
刷新几次,发现和ribbon的效果一样,是轮询的切换。与ribbon的主要区别就是这里的服务调用是真正通过controller调用service的方式。
2.4OpenFeign超时控制和日志打印
2.4.1超时控制
有时候需要对服务提供者进行快速的响应,Feign就可以。Feign默认等待1秒,超过后报错。也就是说Feigin客户端只等待一秒,但是服务端处理过程超过一秒,导致客户端会出错,这就需要我们进行设置超时时间,避免出现这样的情况。
在客户端(服务消费者80)的yml进行配置
#设置feign 客户端超时时间
ribbon:
#指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
ReadTimeout: 5000
#指的是建立连接后从服务器读取到可用资源所用的时间
ConnectTimeout: 5000
2.4.2日志打印
日志级别
NONE:默认的,不显示任何日志
BASIC:仅记录请求方法、URL、响应状态码及执行时间
HEADERS:BASIC信息以及请求和响应的头信息
FULL:HEADERS信息以及请求和响应的正文和元数据
在客户端(服务消费者80)添加配置类LogConfig
package com.zys.cloud.config; import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; //配置feign日志级别
@Configuration
public class LogConfig {
@Bean
Logger.Level feignLevel(){
return Logger.Level.FULL;
}
}
yml配置,指定监控的接口路径
logging:
level:
#配置feign的日志级别 和监控的接口
com.zys.cloud.service.UserClientService: debug
先启动eureka集群,然后服务提供者集群,然后80启动。输入http://localhost/consumer/get/3在idea控制台可以看出多了很多的打印信息。
SpringCloud之服务调用的更多相关文章
- 【微服务】之五:轻松搞定SpringCloud微服务-调用远程组件Feign
上一篇文章讲到了负载均衡在Spring Cloud体系中的体现,其实Spring Cloud是提供了多种客户端调用的组件,各个微服务都是以HTTP接口的形式暴露自身服务的,因此在调用远程服务时就必须使 ...
- SpringCloud商品服务调用方式之feign
简介:改造电商项目 order-service服务 调用商品服务获取商品信息 Feign: 伪RPC客户端(本质还是用http) 官方文档: https://cloud.spring.io/sprin ...
- 三、springcloud之服务调用Feign
一.背景 项目中接口调用: Httpclient Okhttp Httpurlconnection RestTemplate 微服务提供了更简单,方便的Feign 二.Feign简介 Feign是一个 ...
- 微服务SpringCloud之服务调用与负载均衡
上一篇我们学习了服务的注册与发现,本篇博客是在上一篇的基础上学习服务的调用.上一博客主要创建了Eureka的服务端和一个Client,该Client包含了一个Controller用来提供对外服务供外部 ...
- SpringCloud商品服务调用方式之Ribbon
1.创建order_service项目 pom依赖 <dependency> <groupId>org.springframework.boot</groupId> ...
- 四、springcloud之服务调用Feign(二)
一.Fegin的常见应用 Feign的Encoder.Decoder和ErrorDecoder Feign将方法签名中方法参数对象序列化为请求参数放到HTTP请求中的过程,是由编码器(Encoder) ...
- springCloud微服务调用失败【CannotGetJdbcConnectionException: Failed to obtain JDBC Connection】
详情如下: 2019-07-28 10:56:18.229 ERROR 16212 --- [nio-8081-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet ...
- 学习一下 SpringCloud (三)-- 服务调用、负载均衡 Ribbon、OpenFeign
(1) 相关博文地址: 学习一下 SpringCloud (一)-- 从单体架构到微服务架构.代码拆分(maven 聚合): https://www.cnblogs.com/l-y-h/p/14105 ...
- Spring Cloud Feign 优雅的服务调用
Fegin 是由NetFlix开发的声明式.模板化HTTP客户端,可用于SpringCloud 的服务调用.提供了一套更优雅.便捷的HTTP调用API,并且SpringCloud整合了Fegin.Eu ...
随机推荐
- WPF权限控制——【2】模块、菜单、按钮
周末没有工作,没有写博客,因为觉得休息很必要:曾听到一句话是这样说的:"你们得救在乎归回安息:你们得力在乎平静安稳".当我想到太阳没秒钟要燃烧420万吨的燃料时,想到的就是造物主的 ...
- 浅谈Webpack模块打包工具一
为什么要使用模块打包工具 1.模块化开发ES Modules存在兼容性问题 打包之后成产阶段编译为ES5 解决兼容性问题 2.模块文件过多 网络请求频繁 开发阶段把散的模块打包成一个模块 解决网络请 ...
- HDU-6599 I Love Palindrome String(回文自动机+字符串hash)
题目链接 题意:给定一个字符串\(|S|\le 3\times 10^5\) 对于每个 \(i\in [1,|S|]\) 求有多少子串\(s_ls_{l+1}\cdots s_r\)满足下面条件 \( ...
- HDU6403 Card Game【基环树 + 树形DP】
HDU6403 Card Game 题意: 给出\(N\)张卡片,卡片正反两面都有数字,现在要翻转一些卡片使得所有卡片的正面的值各不相同,问最小翻转次数和最小翻转情况下的不同方案数 \(N\le 10 ...
- 2019ICPC南昌邀请赛 Sequence
题意:给出n个点的权值,m次操作,操作为1时为询问,每次询问给出 l 和 r ,求 f(l,r).操作为0时为修改权值.f(l,r)=f(l,l)⊕f(l,l+1)⊕⋯⊕f(l,r)⊕f(l+1,l+ ...
- Buy the Ticket HDU - 1133 大数dp
题意: 演唱会门票售票处,那里最开始没有零钱.每一张门票是50元,人们只会拿着100元和50元去买票,有n个人是拿着50元买票,m个人拿着100元去买票. n+m个人按照某个顺序按序买票,如果一个人拿 ...
- Codeforces Round #345 (Div. 1) C. Table Compression (并查集)
Little Petya is now fond of data compression algorithms. He has already studied gz, bz, zip algorith ...
- c语言实现--不带头结点的单链表操作
1,不带头结点的单链表操作中,除了InitList(),GetElem(),ListInsert(),ListDelete()操作与带头结点的单链表有差别外,其它的操作基本上一样. 2,不带头结点单链 ...
- Broken robot CodeForces - 24D (三对角矩阵简化高斯消元+概率dp)
题意: 有一个N行M列的矩阵,机器人最初位于第i行和第j列.然后,机器人可以在每一步都转到另一个单元.目的是转到最底部(第N个)行.机器人可以停留在当前单元格处,向左移动,向右移动或移动到当前位置下方 ...
- 请问什么时候对象分配会不在 TLAB 内分配
Java 对象分配流程 我们这里不考虑栈上分配,这些会在 JIT 的章节详细分析,我们这里考虑的是无法栈上分配需要共享的对象. 对于 HotSpot JVM 实现,所有的 GC 算法的实现都是一种对于 ...