目录
一、Feign远程调用
先来看我们以前利用RestTemplate发起远程调用的代码:
//通过restTemplate调用商品微服务
String url = "service-product";
Product product = restTemplate.getForObject( "http://"+url+"/product/" + pid, Product.class);
这段代码存在着代码可读性差,编程体验不统一、参数复杂URL难以维护、硬编码等问题。
1、Feign简介
Feign是Spring Cloud提供的一个声明式的伪Http客户端,它使得调用远程服务就像调用本地服务一样简单,只需要创建一个接口并添加一个注解即可。 Nacos很好的兼容了Feign, Feign默认集了Ribbon,所以在Nacos下使用Fegin默认就实现了负载均衡的效果官方地址:https://github.com/OpenFeign/feign。
2、基本使用
加入Fegin的依赖:
<!--fegin组件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
在主类上添加Fegin的注解(shop_order):
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients//开启Fegin
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class);
}
}
也就是@EnableFeignClients是用来启用Feign客户端的支持。Feign是一个声明式的HTTP客户端,使用它可以通过定义接口来调用远程服务。这个注解会扫描指定包或当前包及其子包中的所有Feign客户端接口,并自动将它们注册为Spring Bean。
然后我们在shop_order中的yml文件中配置连接池:
feign:
client:
config:
default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
loggerLevel: FULL # 日志级别
httpclient:
enabled: true # 开启feign对HttpClient的支持
max-connections: 200 # 最大的连接数
max-connections-per-route: 50 # 每个路径的最大连接数
其中enabled如果是false则不会使用HttpClient,而是使用默认的HTTP客户端。
max-connections是设置HttpClient连接池的最大连接数。这个配置决定了可以同时打开的最大HTTP连接数量。
max-connections-per-route是设置每个路由(或目标主机)允许的最大连接数。这个配置有助于控制特定服务的并发连接数,防止对单个服务发起过多的请求而导致压力过大。
总结:
日志级别尽量用basic
使用HttpClient或OKHttp代替URLConnection
- 引入feign-httpClient依赖
- 配置文件开启httpClient功能,设置连接池参数
二、Dubbo
1、基本简介
Dubbo是阿里巴巴开源的基于 Java 的高性能 RPC分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。Spring Cloud Alibaba微服务开发框架集成了Dubbo,可实现微服务对外暴露Dubbo协议的接口,Dubbo协议相比RESTful协议速度更快RPC:RPC是远程过程(RemoteProcedureCall)的缩写形式,调用RPC远程方法就像调用本地方法一样,Dubbo之前阿里研发,中间停止维护2年,最后开启维护并捐献给Apache。
dubbo官网:http://dubbo.io/
以上是 Dubbo 的工作原理图,从抽象架构上分为两层:服务治理抽象控制面 和 Dubbo 数据面。
服务治理控制面。服务治理控制面不是特指如注册中心类的单个具体组件,而是对Dubbo 治理体系的抽象表达。控制面包含协调服务发现的注册中心、流量管控策略、Dubbo Admin 控制台等,如果采用了 Service Mesh 架构则还包含 lstio 等服务网格控制面。
Dubbo 数据面数据面代表集群部署的所有 Dubbo 进程,进程之间通过 RPC 协议实现数据交换,Dubbo 定义了微服务应用开发与调用规范并负责完成数据传输的编解码工作。
- 服务消费者 (Dubbo Consumer),发起业务调用或 RPC 通信的 Dubbo 进程
- 服务提供者 (Dubbo Provider),接收业务调用或 RPC 通信的 Dubbo 进程
2、基础实现
首先是在shop-common中创建一个用于统一业务的方法的接口,这个接口之所以定义在这个地方是因为它是的坐标是要被其他主服务调用使用的,所以把接口定义在实现服务上可以同时调用统一要实现的方法。
/**
实战中,会将所有服务接口设计给一个叫做api的服务,单独维护,此处就在common服务设置
*/
public interface IProductService {
Product findByPid(Integer pid);
}
在服务提供者上加入dubbo依赖(shop-product):
<!-- dubbo -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
然后还是在服务提供者(shop-product)的yml文件上添加dubbo配置:
dubbo:
scan:
base-packages: com.apesource.service.impl
protocols:
dubbo:
name: dubbo
port: -1
registry:
address: spring-cloud://localhost
其中base-packages指定了要扫描的包路径。在这个路径下,Dubbo会自动扫描并注册标注了Dubbo注解(@Service)的类和接口。这些服务将被Dubbo注册到注册中心或被本地消费者引用。
name: dubbo指定使用dubbo协议,这是Dubbo框架的默认协议,基于Netty实现的高性能通信协议。port:-1是表示让Dubbo自动选择一个可用端口进行服务暴露。如果你想指定特定端口,可以将-1
替换为具体的端口号。
registry表示这个节点配置服务注册中心,Dubbo服务会向这里注册或者从这里发现其他服务。spring-cloud表示Dubbo与Spring Cloud集成,借助Spring Cloud的服务注册与发现机制来管理服务。localhost指的是本地注册中心地址。
然后将shop-product模块中的service层实现类的方法进行暴露服务:
//暴露服务:注意这里使用的是dubbo提供的注解@Service,而不是Spring的
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements IProductService,IService<Product> {
@Autowired
ProductMapper productMapper;
@Override
public Product findByPid(Integer pid) {
return productMapper.selectById(pid);
}
}
注意这里的@Service导入的包是dubbo提供的@Service,这个注解用于将当前类作为Dubbo服务暴露出去,供其他微服务消费。
然后我们再去服务消费者中去编写代码(shop-order):
首先是添加依赖:
<!-- dubbo -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
然后去yml中添加配置信息:
dubbo:
registry:
address: spring-cloud://localhost
cloud:
subscribed-services: service-product
这里面也是通过adress配置了Dubbo的注册中心地址,cloud表示这个配置项用于指定Dubbo消费者要订阅的服务名称,这里是把service-product的服务订阅,并且从注册中心获取该服务的可用实例信息。当服务消费者启动时,它会从注册中心中获取service-product服务的地址,并通过Dubbo进行远程调用。
然后我们在shop-order中的服务器去使用service-product服务:
@RestController
public class OrderController {
//引用服务
@Reference
private IProductService productService;
@Autowired
private IOrderService orderService;
//Ribbon下单
@RequestMapping("/order/prod/{pid}")
public Order order(@PathVariable("pid") Integer pid) {
//通过dubbo调用商品微服务
Product product = productService.findByPid(pid);
//下单(创建订单)
Order order = new Order();
order.setUid(1);
order.setUsername("测试用户");
order.setPid(pid);
order.setPname(product.getPname());
order.setPprice(product.getPprice());
order.setNumber(1);
orderService.createOrder(order);
return order;
}
}
@Reference这是Dubbo的注解,用于从注册中心引用远程服务。在这里,它引用了一个刚才在common实体服务中的公共接口IProductService,这个接口又被刚才的ProductServiceImpl所实现,所以这个productService代理对象就是向上转型的ProductServiceImpl对象。它可以调用被调用服务的代码完成查找商品信息操作,这个服务提供了与商品相关的操作。
后面的业务基本和以前的微服务操作一致。