1.服务治理介绍
思考一个问题
服务提供者的网络地址(ip,端口)等硬编码到了代码中,这种做法存在许多问题:
- 一旦服务提供者地址变化,就需要手工修改代码
- 一旦是多个服务提供者,无法实现负载均衡功能
- 一旦服务变得越来越多,人工维护 == 调用关系 == 困难
那么应该怎么解决呢,这时候就需要通过注册中心动态的实现服务治理。
2. 什么是服务治理
服务治理是微服务架构中最核心最基本的模块。用于实现各个微服务的自动注册与发现。
服务注册:在服务治理框架中,都会构建出一个注册中心,每个服务单元向注册中心登记自己提供服务的详细信息。并在注册中心形成一张服务的清单,服务注册中心需要以心跳30s 90s的方式去检测清单中的服务是否可用,如果不可用,需要在服务清单中剔除不可用的服务。
服务发现:服务调用方向服务注册中心咨询服务,并获取所有服务的实例清单,实现对具体服务实例的访问。
2.1.常见的服务治理组件。
- eureka:它是netfilx公司提供的一款组件,这款组件已经停止更新。、
- nacos:它是阿里巴巴提供的一款服务治理组件。
- zookeeper:它是apache公司提供的服务治理组件。
- consul:服务治理组件
2.2 安装nacos治理组件
解压到当前目录 --- 不要带中文
双击startup.cmd
账号和密码:
nacos/nacos
2.3 微服务注册到注册中心
(1)product类引入nacos依赖
<!--引入nacos依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
(2)配置文件指定注册中心的地址
#配置文件指定注册中心的地址
#pei zhi wen jian zhi ding zhu ce zhong xin de di zhi
spring.cloud.nacos.discovery.server-addr=localhost:8848
(3)为微服务起名
#起名
#qi ming
spring.application.name=qy163-product
(4)启动主启动类
(5)微服务由nacos来管理
(1)order类引入nacos依赖
<!--引入nacos依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
(2) 修改订单微服务order的代码
(3)启动order主启动类
(4)访问order类Controller层的方法地址
3.实现负载均衡
3.1什么是负载均衡
通俗的讲,负载均衡就是将负载(工作任务,访问请求)进行分摊到多个操作单元(服务器,组件)上进行执行。
可以手动完成负载均衡。
(1)修改order调用方
(2)给product类配置集群
(3)启动order类 和 product类
(4)访问order类的方法路径
(5)观察product类的日志
都打印了sql语句 说明随机负载均衡可以成功
3.2 使用ribbon完成负载均衡
上面的负载均衡,是自己写的代码。缺点:代码比较复杂。如果想改变负载均衡的策略,必须都是修改order的代码。
什么是ribbon
ribbon是Netflix发布的一个负载均衡器,有助于控制HTTP和TCP客户端行为。在SpringCloud中,nacos一般配置Ribbon进行使用,Ribbon提供了客户端负载均衡的功能,Ribbon利用从nacos中读取到的服务信息,在调用服务节点提供的服务时,会合理(策略)的进行负载。在SpringCloud中可以将注册中心和Ribbon配合使用,Ribbon自动的从注册中心中获取提供者的列表信息,并基于内置的负载均衡算法,请求服务。
基于Ribbon实现服务调用,是通过拉取到的所有服务列表组成(服务名-请求路径的)映射关系。 借助RestTemplate最终进行调用
如何使用ribbon
(1)在RestTemplate类上加个注解 @LoadBalance
@Bean
@LoadBalanced //springcloud在扫描时会帮你完成从注册中心拉取服务清单的功能
public RestTemplate restTemplate(){
return new RestTemplate();
}
(2)修改Controller层代码
(3)启动类
(4)访问order的方法路径
(5)product类打印出日志 表示成功
ribbon内置的负载均衡策略
ribbon内置了多种负载均衡策略,内部负载均衡的顶级接口为com.netflix.loadbalancer.IRule,具体的负载均衡策略如下所示:
如何改变ribbon的负载均衡策略
修改order的配置文件
#修改ribbon负载策略
qy163-product.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
#qy163-product:表示对访问哪个微服务设置负载均衡策略
#com.netflix.loadbalancer.RoundRobinRule:负载均衡策略类
使用ribbon完成了从nacos自动拉取服务,并完成负载均衡功能。
4.使用Openfeign完成远程调用
上面服务之间的调用 使用的是RestTemplate.使用Resttemplate远程调用,它不符合我们的编程习惯。我们的编程习惯 Controller -- Service --- Dao 在Controller注入一个Service对象,然后调用Service中的方法,根据方法传递相应的参数以及接收方法的返回结果。
我们可以使用Openfeign组件来完成
4.1什么是Openfeign
OpenFeign是SpringCloud提供的一个声明式的伪Http客户端,它使得调用完成服务就像调用本地服务一样简单,只需要创建一个接口并添加一个注解即可。
Nacos很好的兼容了OpenFeign,OpenFeign负载均衡默认集成了Ribbon,所以在Nacos下使用OpenFeign默认就实现了负载均衡的效果。
总结:OpenFeign就是为了完成服务的远程调用,它就像调用本地方法一样。
4.2如何使用OpenFeign
(1)引入OpenFeign依赖
<!--引入OpenFeign依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
(2)定义接口并添加@FeignClient(value = "服务提供者的名字") 注解
//@FeignClient(value = "服务提供者的名字")
@FeignClient(value = "qy163-product")
@RequestMapping("product")
public interface ProductOpenFeign {
//抽象方法一定要和服务提供者的接口方法一样
@GetMapping("getById/{pid}")
public Product getById(@PathVariable Integer pid);
}
(3)在启动类开启OpenFeign注解驱动
@SpringBootApplication
@MapperScan(basePackages = "com.aaa.order.dao")
@EnableFeignClients //开启OpenFeign注解驱动
public class OrderApp {
public static void main(String[] args) {
SpringApplication.run(OrderApp.class,args);
}
@Bean
@LoadBalanced //springcloud在扫描时会帮你完成从注册中心拉取服务清单的功能
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
(4)在使用的类中注入OpenFeign接口
package com.aaa.order.controller;
import com.aaa.order.feign.ProductOpenFeign;
import com.aaa.order.service.OrderService;
import com.aaa.pojo.Order;
import com.aaa.pojo.Product;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
import java.util.Random;
/**
* @program: qy163-2
* @description:
* @author: 王永亮
* @create: 2023-05-12 17:36
**/
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private OrderService orderService;
//注入OpenFeign接口
//springcloud 扫描到@FeignClient注解后,就会为该注解接口生成一个代理实现类,再把代理实现类注册该相应的属性
@Autowired
private ProductOpenFeign productOpenFeign;
@GetMapping("save")
public String save(Integer pid,Integer num){
Order order = new Order();
///用户信息 --登录中获取
order.setUid(1);
order.setUsername("wyl");
order.setNumber(num);
Product product = productOpenFeign.getById(pid);
if(product == null){
return "下单失败";
}
order.setPid(product.getPid());
order.setPname(product.getPname());
order.setPprice(product.getPprice());
Integer save = orderService.save(order);
return save > 0 ? "下单成功" : "下单失败";
}
}
(5)重新部署order类
(6)访问方法路径
(7)控制台打印出sql 日志 表示成功
总结:
5. eureka作为注册中心
它的官网没有提供下载包。只能自己创建eureka的服务端。
(1)搭建eureka服务
(2)引入eureka依赖
<!--eureka依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
(3)配置文件
server.port=7001
eureka.instance.hostname=localhost
#是否把该服务注册到eureka服务上
eureka.client.register-with-eureka=false
#是否该服务从注册中心eureka上拉取服务
eureka.client.fetch-registry=false
#微服务访问eureka访问的地址
eureka.client.service-url.defaultZone=http://localhost:7001/eureka/
security.basic.enabled=false
(3)主启动
@SpringBootApplication
@EnableEurekaServer
public class EurekaApp {
public static void main(String[] args) {
SpringApplication.run(EurekaApp.class,args);
}
}
其他微服务引入eureka客户依赖
<!--引入eureka客户依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
配置文件
#eureka注册中心地址
eureka.client.service-url.defaultZone=http://localhost:7001/eureka/
启动product类
访问eureka注册中心