SpringCloud Feign的基本概念与应用
本文介绍了一些关于SpringCloud Feign的基本概念与应用。
RestTemplate
由于微服务架构,无法直接请求其他服务的service,需要远程调用,因此会用到RestTemplate来做远程调用。同时我们使用Ribbon结合RestTemplate来实现使用服务名称代替ip和端口以及负载均衡。Feign则是一种更加优雅的方式,不会需要像RestTemplate一样出现url
使用方法
首先添加依赖
<dependency> |
然后主启动类上加上@EnableFeignClients注解,就像@EnableEurekaServer注解一样
在Service接口上添加@FeignClient注解,并且指定服务的名称(注册到服务注册中心的名称),因此这里就可以实现跨服务调用,只需要实现注册其他服务的名称的接口。使用起来的整体感觉像controller
|
Feign配置
方式一:通过修改yml文件对feign进行配置
# OrderService |
方式二:通过配置类和注解
创建一个configuration类,配置Logger.Level这个Bean,加在指定服务的@FeignClient(value = “userservice”)注解中,或者加在启动类的@EnableFeignClients( defaultConfiguration = xxxconfiguration.class )注解中。
Feign性能优化
Feign底层默认使用的URLConnection,不支持连接池,可以通过使用Apache HttpClient来支持连接池(减少连接的创建与释放)
使用方法
添加HttpClient依赖
<dependency> |
配置连接池
feign: |
Feign-Api
controller和FeignClient的重合度较高,可以通过采用定义接口,让二者都去继承这个接口,利用这种方式提供便捷。
存在的问题:紧耦合
我更偏向的方法是将FeignClient、POJO、Feign的默认配置封装到一个模块中,通过引入模块来供其他消费者使用。这样做也可以避免每个服务都要去实现一样的FeignClient,创建实体类等。
存在的问题:有的服务可能仅仅需要部分实体类和功能,有所冗余
使用方法
在其他服务的pom文件中引入该feign-api的依赖,这样就可以引入本模块中未创建的实体类,实现复用
在使用过程中会出现一个问题:对FeignClient的自动装配,@Autowired只能装配项目所在包目录下的Bean,因此需要在@EnableFeignClients注解上添加clients参数。
@EnableFeignClients( clients = {UserClient.class, OrderClent.class}, defaultConfiguration = xxxconfiguration.class ) clients参数可以是数组
总结
流程梳理:
- 服务模块不需要实现FeignClient来实现跨服务,不需要创建其他的实体
- 通过创建feign-api来对服务进行封装,为其他服务的跨服务调用提供接口,同时减少了实体类重复写的情况
开发流程:
provider的服务相关内容按照springboot一样照常写,然后在provider-api中提供对服务controller的访问,其他服务需要跨服务调用时通过provider-api来从其它服务的controller中获取
题外话
昨晚一直在思考前端到底是如何调用有多个实例的后端服务,为此去了解了一下nginx的负载均衡和反向代理。
我的纠结点在于,我目前学到的springcloud内部的负载均衡都是服务之间的调用,可以通过其他服务的名称向注册中心进行请求,然后再根据返回的服务实例列表负载均衡。那如果这个服务本身我从前端向他发起请求,又应该怎么做才能不访问固定的端口号呢?
最初想到的方法是将对这台主机的http请求,全部向nacos寻找服务名称的这种方式,当然只是我的猜想。今天查资料,貌似是通过向网关发出请求,再由网关进行路由到具体服务。就我个人而言,从设计的角度感觉非常合理,前端的请求可以通过nginx的负载均衡向不同网关实例发送,网关又可以根据url的路径向具体的服务请求,服务则又被注册到了nacos,若存在多个实例也会在openfeign中实现负载均衡。
莫名其妙就串联起来了,学完网关再看看