1.前言
经过上一篇博客的Eureka学习后,接下来我们正式开始服务间调用组件的学习,目前常用的服务间调用组件有Ribbon和OpenFeign,这里我们就重点来学习一下这两个组件的使用。
2.Ribbon
Ribbon是一个基于 HTTP 和 TCP 客户端的负载均衡器
Ribbon也算是Spring Cloud Netflix体系的常规组件,Ribbon提供了内部调用以及负载均衡的能力,此处我们先来看下内部调用。
其原理图如下所示:
- 像之前一样建立名为ribbon-client的模块,同样记得在选择依赖时选择Spring Web、Eureka Discovery、Ribbon,如图所示:
- 修改配置文件application.yml,代码如下:
server:
port: 18765
eureka:
instance:
hostname: localhost
client:
service-url:
defaultZone: http://${eureka.instance.hostname}:18761/eureka/
spring:
application:
name: service-ribbon
- 修改启动类,我们知道Ribbon之所以调用内部接口,依靠的完全是RestTemplate对象来完成,所以我们先注入RestTemplate到Spring管理。
代码如下:
package com.springclouddemo.ribbonclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
public class RibbonClientApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonClientApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
- 接下来,创建一个HiService类,表示要远程调用的接口服务,注意这里的uri名字要和调用的
application-name
相同,即上一篇博客中eureka-client
中配置过的,代码如下:
package com.springclouddemo.ribbonclient.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
/**
* @author 莫息涛
* @Description: Ribbon的测试服务类
* @date 2020/2/24 11:54
*/
@Service
public class HiService {
@Autowired
RestTemplate restTemplate;
public String hiService() {
return restTemplate.getForObject("http://SERVICE-HI/hi",String.class); //注册的服务名称
}
}
- 创建一个HiController,调用HiService的方法,代码如下:
package com.springclouddemo.ribbonclient.controller;
import com.springclouddemo.ribbonclient.service.HiService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 莫息涛
* @Description: Ribbon的对外测试接口
* @date 2020/2/24 11:54
*/
@RestController
public class HiController {
@Autowired
HiService hiService;
@RequestMapping(value = "/hi")
public String hi(){
return hiService.hiService();
}
}
- 按照顺序依次启动
eureka-server
,eureka-client
,ribbon-client
,访问注册中心页面,可以看到ribbon模块已经启动,如图所示:
- 访问
http://localhost:18765/hi
,可以看到如下显示结果,说明ribbon配置成功,如图所示:
3.OpenFeign
Feign(现在改名叫OpenFeign)是Spring Cloud的公共组件,不属于netflix,它也是用来进行服务间调用的,那么读者们是不是有一个疑问?有了Ribbon为什么还要有Feign。
有没有考虑过,虽然Ribbon使用RestTemplate形式进行服务间调用,但是对我们来说,我们更想接近的是如同Dubbo或者普通方法调用那个直接来调用Demo-Service提供的服务,那么这个时候Ribbon是不可以的,所以我们只能使用Feign来完成。
- 像之前一样建立名为openfeign-client的模块,同样记得在选择依赖时选择Spring Web、Eureka Discovery、OpenFeign,如图所示:
- 修改配置文件application.yml,代码如下:
server:
port: 18764
eureka:
instance:
hostname: localhost
client:
service-url:
defaultZone: http://${eureka.instance.hostname}:18761/eureka/
spring:
application:
name: service-openfeign
- 修改启动类,添加注解
@EnableFeignClients
,表示这是一个Feign的客户端,代码如下:
package com.springclouddemo.openfeignclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class OpenfeignClientApplication {
public static void main(String[] args) {
SpringApplication.run(OpenfeignClientApplication.class, args);
}
}
- 定义一个远程调用接口HiInterface ,添加注解
@FeignClient
以调用相应服务,代码如下:
package com.springclouddemo.openfeignclient.Interface;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* @author 莫息涛
* @Description: Feign的测试接口
* @date 2020/2/24 10:48
*/
@FeignClient(value = "service-hi")
public interface HiInterface {
@RequestMapping(value = "/hi",method = RequestMethod.GET)
String hi();
}
- 创建HiController ,用来外访问从而获取远程接口内容,代码如下:
package com.springclouddemo.openfeignclient.controller;
import com.springclouddemo.openfeignclient.Interface.HiInterface;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 莫息涛
* @Description: Feign的对外测试接口
* @date 2020/2/24 10:50
*/
@RestController
public class HiController {
@Autowired
HiInterface hiInterface;
@RequestMapping("hi")
public String hi(){
return hiInterface.hi();
}
}
- 按照顺序依次启动
eureka-server
,eureka-client
,openfeign-client
,访问注册中心页面,可以看到openfeign模块已经启动,如图所示:
- 访问
http://localhost:18764/hi
,可以看到如下显示结果,说明openfeign配置成功,如图所示:
4.服务间调用组件的负载均衡
事实上,在以上两个模块编写完成后,就已经基本展示了服务间调用组件的作用。然而,为了体现服务间调用组件的负载均衡特性,我们再添加一个与eureka-client一模一样的模块,取名为eureka-client2
,唯一的区别是修改其端口号为18763。
这里我们用OpenFeign作为例子,使用Ribbon也同理。
按照顺序依次启动eureka-server
,eureka-client
,eureka-client2
,openfeign-client
,访问注册中心页面,观察注册中心页面,如图所示:
可以看到这里出现了两个SERVICE-HI
服务,而访问的端口不同。
我们通过OpenFeign不断来访问这个服务,可以看到会出现两种不同的结果,如图所示:
这说明OpenFeign内部采用了负载均衡的原理,可以访问相同的uri而抓发到不同的请求,默认的负载均衡为轮询模式