SpringCloud Alibaba
SpringCloud是一系列分布式框架的集合,基于Spring Boot进行开发,将不同公司生产的不同组件进行集成,以SpringBoot的风格进行集成,开发者不需要关注底层的整合实现,而是开箱即用,需要哪个组价就用SpringBoot整合进来。
服务治理
服务注册+服务发现——Nacos-注册中心
步骤:
打开nacos
provider——导入依赖,配置nacos信息
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
spring.cloud.nacos.discovery.server-addr=localhost:8848
spring.application.name=provider
server.port=8081
management.endpoints.web.exposure.include=*
spring.cloud.sentinel.transport.dashboard=localhost:8080
spring.cloud.sentinel.filter.enabled=false
//provider
@RestController
public class ProviderController {
@Value("${server.port}")
private String port;
@Autowired
TestService testService;
@RequestMapping("/index")
public String index(){
return this.port;
}
@RequestMapping("/list")
public String list(){return this.port;}
@RequestMapping("/test1")
public String test1(){
testService.Test();
return "test1";
}
@RequestMapping("/test2")
public String test2(){
testService.Test();
return "test2";
}
}
idea一个项目并行运行,一个项目启动多个实例方法
配置成功之后,只需要修改properties的端口号,再次运行就可以启动该端口号的实例
Ribbon
Ribbon 不是Spring Cloud Alibaba的组件,是Netflix提供的
默认是轮询算法,还有随机算法,权重算法、、主要三个
步骤:延续nacos步骤
创建消费者consumer——导入nacos依赖(与provider一致)——consumer controller调用提供者的接口
需求:多个服务器,但是由于没有算法,默认肯定是全部请求只访问其中一个服务器,请求过多导致压力大,服务器容易奔溃。所以现在我们现在要设计算法来进行负载均衡。
不使用Ribbon:
@RestController
public class ConsumerController {
@Autowired
private DiscoveryClient discoveryClient;//利用它去连接nacos
@Autowired
private RestTemplate restTemplate;//在配置类中自动装载
@RequestMapping("/instances")
public List<ServiceInstance> instances(){
//根据service 的 id,返回指定service的服务实例
return discoveryClient.getInstances("provider");
}
@GetMapping("/index")
public String index(){
//调用provider的index方法:先找到provider实例,再调用方法
List<ServiceInstance> instances = instances();
//随机数(0-2)
int index = ThreadLocalRandom.current().nextInt(instances.size());
ServiceInstance serviceInstance = instances.get(index);//获取具体实例
//拿到该实例的uri = IP+端口
String url = serviceInstance.getUri()+"/index";
//调用方法
return "调用了端口为"+serviceInstance.getPort()+"的服务:"+restTemplate.getForObject(url,String.class);
}
}
使用Ribbon:不进行配置,默认轮询算法
@RestController
public class RibbonController {
//Ribbon 负载均衡默认采用轮询算法,依次调用
@Autowired
private DiscoveryClient discoveryClient;//作用:连接nacos
@Autowired
private RestTemplate restTemplate;//作用:调用其他服务
@GetMapping("instance")
public List<ServiceInstance> instance(){
return discoveryClient.getInstances("provider");
}
@GetMapping("/index")
public String index(){
return restTemplate.getForObject("http://provider/index",String.class);
}
}
需要注意的是:RestTemplate并不会自动装配,需要自定义配置类
@Configuration
public class ConsumerConfiguration {
//restTemplate不会自动装载所以要在配置类中手动装载
@Bean
@LoadBalanced //将Ribbon加进来了-负载均衡
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
随机算法在消费者的application.properties添加配置:provider.ribbon.NFLoadBalancerRuleClassName:com.netflix.loadbalancer.RandomRule
基于权重的算法:
权重一致时,还是随机
- 配置阿里写好的类,NacosWeightedRule
- 同样在application.properties中配置(步骤一类的全限定名)
@Slf4j
public class NacosWeightedRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties
nacosDiscoveryProperties;
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {//读取配置文件
}
@Override
public Server choose(Object o) {
ILoadBalancer loadBalancer = this.getLoadBalancer();
BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) loadBalancer;
//获取要请求的微服务名称
String name = baseLoadBalancer.getName();
//获取服务发现的相关API
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
try {
Instance instance = namingService.selectOneHealthyInstance(name);
return new NacosServer(instance);
} catch (NacosException e) {
e.printStackTrace();
return null;
}
}
}