个人中心:https://blog.csdn.net/hello_list
前情提要:
首先我们要知道ribbon是什么,是来做负载均衡的(基于客户端),下面是介绍,可以看下
Spring Cloud Ribbon 是基于Netflix Ribbon 实现的一套客户端负载均衡的工具。
简单的说,Ribbon 是 Netflix 发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将 Netflix 的中间层服务连接在一起。Ribbon 的客户端组件提供一系列完整的配置项,如:连接超时、重试等。简单的说,就是在配置文件中列出 LoadBalancer (简称LB:负载均衡) 后面所有的及其,Ribbon 会自动的帮助你基于某种规则 (如简单轮询,随机连接等等) 去连接这些机器。我们也容易使用 Ribbon 实现自定义的负载均衡算法!
1、导入依赖,如果是跟着我这个走的,我这里使文章日期最新版,Eureka里面已经集成了Ribbon所以不用再去导入Ribbon单独的依赖,还会造成依赖冲突。我这里的是1.4.7.RELEASE,如果想要单独使用就导入这个包,并且排除Eureka
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-ribbonartifactId>
<version>2.2.9.RELEASEversion>
dependency>
2、编写配置,我们知道ribbon是基于客户端,所以我们80里面配置下ribbon,配置下eureka,这里不用像注册中心注册自己,但是需要去注册中心发现服务
#Eureka配置
eureka:
client:
# 服务端不用向注册中心注册
register-with-eureka: false
#参考链接:https://blog.csdn.net/qq_45225798/article/details/120267548
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
开启负载均衡
3、开启功能,启动类,Eureka客户端
这里我们再修改下,我们之前rest是根据IP地址端口找找到服务,这里我们是通过注册中心服务发现,直接使用我们的服务名去调用服务
我们把注册中心7001或者都开启,反正开一个,然后8001服务开启,之后我们启动80客户端去调用服务,测试,这里的话我是都开了
我这里启动80报错了,不知道为什么,我在写文之前测试是可以的,现在已启动,报错了,是因为我在api里加了一个@TableId主键注解,但是写之前测试就没错
我们可以这样解决,排除下
启动成功,我们来看下注册中心,集群以及服务都注册了进来
我们来试着客户端从注册中心调用服务,调用成功,我才想起来这里我们是做负载均衡,当然负载均衡就实现了,但是因为我们服务提供者只有一个8001,我们再多来几个服务提供者,再来两个吧8002,8003
再开两个服务,应该会吧,可简单就是复制粘贴,那我么再来新建两个maven项目
1、导入依赖
2、编写配置
1,3步是不是又可以省去,配置这里得改下,知道改哪里吗
8002,这里我们改下
8003也改下
3、启动服务
这次我们启动一个注册中心7001,然后开启8001,8002,8003服务,我们再开启80客户端去测试负载均衡,这里我们只访问一个服务,为了直观,我们这样修改下
本来我是打算直接看控制台输出,但是为了不直观,想加一句话,但是发现我们用的是mybatis-plus自定义生成service,而且三个服务我们都已经测试好的,这个时候我们就想到了aop,可以帮我们切入,也不用修改现有代码
这里我们临时加一个配置类
1、导入aop依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-aopartifactId>
dependency>
2、编写配置
package com.xuexi.config;
// 表示当前的类是一个配置类
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.context.annotation.Configuration;
@Configuration
//该注解只能用在类上,作用:代表当前类是一个切面类,等价于spring.xml中的标签
//所以现在有了切面,还需要 通知 + 切入点
// 切面 == 通知 + 切面
@Aspect
public class MyAdviceConfig {
/**
* @param joinPoint
* @Before:前置通知
* value:切入点表达式 二者加起来构建成为一个切面
* JoinPoint:连接点:可以理解为两个圆形的切点,从这个切点就可以获取到当前执行的目标类及方法
* 前置通知和后置通知的参数的都是 JoinPoint, 前置后置通知都没有返回值
*/
// 方法级别:具体到某个具体的方法
// @Before(value = "execution(* com.xuexi.service.impl.*.*(..))")
// 表示service包下的所有类所有方法都执行该前置通知
/* @Before(value = "within(com.liu.aop.service.*)")
public void before(JoinPoint joinPoint) {
System.out.println("before开始执行查询.......");
System.out.println("正在执行的目标类是: " + joinPoint.getTarget());
System.out.println("正在执行的目标方法是: " + joinPoint.getSignature().getName());
}*/
static int count = 1;
/**
* 后置通知,属性参数同上面的前置通知
* @param joinPoint 前置通知和后置通知独有的参数
*/
@After(value = "execution(* com.xuexi.service.impl.*.*(..))")
public void after(JoinPoint joinPoint) {
System.out.println("8001服务执行=========>>"+count+"次");
count++;
}
/**
* @param proceedingJoinPoint 环绕通知的正在执行中的连接点(这是环绕通知独有的参数)
* @return 目标方法执行的返回值
* @Around: 环绕通知,有返回值,环绕通知必须进行放行方法(就相当于拦截器),否则目标方法无法执行
*/
/* @Around(value = "execution(* com.xuexi.service.impl.*.*(..))")
public Object aroud(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("aroud环绕通知开始.......");
System.out.println("执行的目标类 = " + proceedingJoinPoint.getTarget());
System.out.println("执行的目标方法 = " + proceedingJoinPoint.getSignature().getName());
// 必须方法目标方法
Object proceed = proceedingJoinPoint.proceed();
System.out.println("aroud环绕通知结束.......");
// 将目标方法的返回值进行返回,否则调用目标方法的方法无法获取到返回值
return proceed;
}*/
}
这是8001的编写,8002,8003就不用多说了吧,就是在执行方法后,在控制台打印信息
8002
8003
开启测试,然后我们看后台控制台打印信息,下面是我们启动的
这样我们就都启动起来,并且服务注册上了
我们通过80客户端去测试,虽然我们实现了服务轮询,但是aop没有切入,我第一反应就是mybatisplus通用mapper和service并不在自己创建的方法中去执行sql,而这些只是通用方法的配置,留下来是为了保留mybaits的子定义
同时我单独建了一个服务测试了下,确实和我想的一样。
我先是在网上搜了下方法,mybatisplus整合aop,没搜到,吃饭去了,也没怎么想吧,平常遇到bug最好的解决办法就是,那会别死较劲,证明你该去干别的事了,果然当我下午再打开电脑的时候,鼠标一点,我们可以对这个方法进行aop,如果外面是配置,这个里面就是具体的sql拼接实现方法。
我们修改,三个配置类都修改下
我们继续测试,可以看到三个服务都注册了进来
用客户端访问,访问服务成功
我们多敲几下,9下吧,我们敲了9下,然后加上最开始一下总共10下,再敲两下吧,我们看这三个服务的调用情况
8001执行了4次
8002也是4次
8003也是四次
看到了吧。3*4=12,就是轮询对吧,平均轮询的负载均衡就实现了;
虽然Eureka继承了Ribbon但是我一直搜不到自定义策略类,所以又加上了这个依赖
1、导入依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-ribbonartifactId>
<version>2.2.9.RELEASEversion>
dependency>
这里IRule,我们shift+shift搜一下这个类,我们可以看到这个类下面有很多自定义类,比如RandomRule随机、RoundRobinRule 轮询等;
这里我们试着改变负载均衡策略为随机,只需要这样即可;
我们再来测试下,服务都注册进来了
我们访问 ,直接连敲12下,看下效果,12次全到8001上了
再多敲几下,可能是连敲的太快,然后基本上都打到8001上了,慢点儿的话还是随机的
8001
8002
8003
到这里呢,其实会有依赖问题,这里你如果没有那就可以了,如果有,可以这样换了依赖
feign也是用来做负载均衡的,但是与Ribbon不同,Ribbon是基于客户端,而Feign是社区的面向接口编程,看下面;
Feign是声明式Web Service客户端,它让微服务之间的调用变得更简单,类似controller调用service。SpringCloud集成了Ribbon和Eureka,可以使用Feigin提供负载均衡的http客户端。
废话不多说,直接上手体验,快速上手;
我们新建一个项目,因为通过客户端去测试,我们把80复制下,修改下,我们这里不拿服务端测试,我们这里更改下api里面做一个service接口:
1、导入依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-feignartifactId>
<version>1.4.7.RELEASEversion>
dependency>
2、编写配置,代码
api中新建一个service接口
在我们新建的feign中,接口编程api中service类接口调用
3、开启功能
其实这里还是基于Ribbon的策略,但是社区认为这样的调用方法更符合java方式,调用接口service,我们现在的策略还是默认轮询,我们把7001打开,然后8001,8002,8003打开然后测试下:
注册中心服务都注册进来了
我们通过80测试,然后连敲12下
我们看下,8001
8002
8003
其实只是认为java应该调用接口service然后去实现,所以只是变化了一个风格,还是依赖ribbon实现负载均衡
看到这里了还不点个关注三连吗,收藏不等于学会,还是要亲自动手实践,bye~