服务注册、服务发现、OpenFeign及其OKHttp连接池实现
目录
一、服务注册
二、服务发现
OpenFeign:
OKHTTP:
一、服务注册
接前篇文章,我们在将Nacos当中注册服务;这里以item-service为例将其注册到Nacos
1.引入依赖:
在item-service
的pom.xml
中添加依赖:
<!--nacos 服务注册发现-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2.在yml文件中配置nacos地址:
item-service下的
application.yml:
spring:application:name: item-service # 服务名称cloud:nacos:server-addr: 192.168.150.101:8848 # nacos地址
这样启动之后就会自动注册;
为了测试一个服务多个实例的情况,我们再配置一个item-service
的部署实例:
然后配置启动项,注意重命名并且配置新的端口,避免冲突:
重启item-service
的两个实例:
访问nacos控制台,可以发现服务注册成功:
点击详情,可以查看到item-service
服务的两个实例信息:
二、服务发现
服务发现的前两步和服务注册一致,多了个第三步的发现并调用服务
<!--nacos 服务注册发现-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
spring:cloud:nacos:server-addr: 192.168.150.101:8848
接下来,服务调用者cart-service
就可以去订阅item-service
服务了。不过item-service有多个实例,而真正发起调用时只需要知道一个实例的地址。
因此,服务调用者必须利用负载均衡的算法,从多个实例中挑选一个去访问。常见的负载均衡算法有:
-
随机
-
轮询
-
IP的hash
-
最近最少访问
-
...
这里我们可以选择最简单的随机负载均衡。
另外,服务发现需要用到一个工具,DiscoveryClient,SpringCloud已经帮我们自动装配,我们可以直接注入使用:
接下来,我们就可以对原来的远程调用做修改了,之前调用时我们需要写死服务提供者的IP和端口:
但现在不需要了,我们通过DiscoveryClient发现服务实例列表,然后通过负载均衡算法,选择一个实例去调用:
这里更正一下上一篇文章的说法,之前提到服务注册能够替代服务调用,实际上并不是,而是相辅相成,两者共同达成我们的目的
OpenFeign:
由于这段代码比较繁杂,且要自己实现,倘若以后其他地方也需要这样调用代码就很冗余,所以我们引入OpenFeign来优化这段代码
首先我们需要引入依赖:
<!--openFeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--负载均衡器--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>
接下来,我们在cart-service
的CartApplication
启动类上添加注解,启动OpenFeign功能:
在cart-service
中,定义一个新的接口,编写Feign客户端:
package com.hmall.cart.client;import com.hmall.cart.domain.dto.ItemDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;import java.util.List;@FeignClient("item-service")
public interface ItemClient {@GetMapping("/items")List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);
}
这里只需要声明接口,无需实现方法。接口中的几个关键信息:
-
@FeignClient("item-service")
:声明服务名称 -
@GetMapping
:声明请求方式 -
@GetMapping("/items")
:声明请求路径 -
@RequestParam("ids") Collection<Long> ids
:声明请求参数 -
List<ItemDTO>
:返回值类型
有了上述信息,OpenFeign就可以利用动态代理帮我们实现这个方法,并且向http://item-service/items
发送一个GET
请求,携带ids为请求参数,并自动将返回值处理为List<ItemDTO>
。
我们只需要直接调用这个方法,即可实现远程调用了。
最后,我们在cart-service
的com.hmall.cart.service.impl.CartServiceImpl
中改造代码,直接调用ItemClient
的方法:
OKHTTP:
通过研读OpenFeign的底层代码发现,其发送请求时用的是HttpURLConnection(jdk自带),其每一次调用都要手动建立连接,然后用InputStream流的方式进行读写,效率低下,于是我们引入带有连接池的客户端OKHttp
在cart-service
的pom.xml
中引入依赖:
<!--OK http 的依赖 -->
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-okhttp</artifactId>
</dependency>
在cart-service
的application.yml
配置文件中开启Feign的连接池功能:
feign:okhttp:enabled: true # 开启OKHttp功能
这样我们就实现了连接池,重启之后即可生效