Spring Cloud 微服务实战系列-Ribbon入门RestTemplate 介绍

本文详细介绍了Ribbon的各个主要模块及其在客户端负载均衡中的应用,包括如何在项目中创建并配置Ribbon。接着展示了RestTemplate如何与Ribbon整合,通过实例演示了使用RestTemplate进行GET和POST请求的方法,简化了通过Ribbon调用服务的步骤,提高了开发效率。
摘要由CSDN通过智能技术生成

导语
  目前在开发中主要的负载均衡方案分为两种;一种是集中式的负载均衡,在生产者和消费者之间通过F5或者是Nginx来进行负载均衡,而另一种则是在客户端自己进行负载均衡,也就是说请求客户端可以根据自己的能力来进行负载。Ribbon就是属于客户端负载均衡的一种。

Ribbon介绍

  Ribbon 的主要模块如下:

  • ribbon-loadbalancer 负载均衡模块,可以单独的进行使用,也可以整合到其他模块中进行使用,其中主要提供的就是Ribbon自定义实现的一些负载均衡算法
  • ribbon-eureka: 基于Eureka进行封装的模块,主要使用可以方便的集成到Eureka中。
  • ribbon-transport:主要是基于Netty的多协议支持,例如TCP、UDP、HTTP等。
  • ribbon-httpclient: 基于Apache HttpClient 进行封装的REST Ful风格的客户端,天然集成了负载均衡算法,可以在项目中直接进行接口的调用。
  • ribbon-example:从名称上可以看到就是给出了一些ribbon的示例代码。
  • ribbon-core:核心代码模块。

Ribbon的使用

  通过下面一个小例子来看看Ribbon在实际项目中如何使用。

创建项目导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.nihui.springcloud.ribbon</groupId>
    <artifactId>base-ribbon</artifactId>
    <version>1.0-SNAPSHOT</version>


    <dependencies>
        <dependency>
            <groupId>com.netflix.ribbon</groupId>
            <artifactId>ribbon</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>com.netflix.ribbon</groupId>
            <artifactId>ribbon-core</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>com.netflix.ribbon</groupId>
            <artifactId>ribbon-loadbalancer</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>io.reactivex</groupId>
            <artifactId>rxjava</artifactId>
            <version>1.0.10</version>
        </dependency>
    </dependencies>


</project>

编写测试类

public class MainApplication {
    public static void main(String[] args) {
        List<Server> serviceList = Arrays.asList(
                new Server("localhost",8080),
                new Server("localhost",8083));

        ILoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder()
                .buildFixedServerListLoadBalancer(serviceList);


        for (int i = 0; i < 5; i++) {
            String result  = LoadBalancerCommand.<String>builder()
                    .withLoadBalancer(loadBalancer)
                    .build()
                    .submit(new ServerOperation<String>() {
                        public Observable<String> call(Server server) {
                            try {
                                String addr = "http://" + server.getHost() + ":" +
                                        server.getPort() + "/user/hello";
                                System.out.println("调用地址" + addr);
                                URL url = new URL(addr);
                                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                                connection.setRequestMethod("GET");
                                connection.connect();
                                InputStream in = connection.getInputStream();
                                byte[] data = new byte[in.available()];
                                in.read(data);
                                return Observable.just(new String(data));
                            } catch (Exception e) {
                                return Observable.error(e);
                            }
                        }
                    }).toBlocking().first();
            System.out.println("调用结果"+result);
        }
    }
}

  通过上面这个例子主要是看看,Ribbon如何进行负载均衡操作,其中在接口调用的最底层还是通过HttpURLConnection。当然因为是RESTFul风格的调用,也可以使用其他的HTTP客户端工具进行操作。

RestTemplate 整合 Ribbon使用

  在上面的例子中使用了HTTP客户端进行调用,在Spring提供了一个用来进行HTTP调用的模板类。这就是RestTemplate。
  那么怎么使用RestTemplate来整合Ribbon进行调用呢,首先就来说明一下Spring RestTemplate如何进行使用。

Get方式调用

  首先要做的事情就是将RestTemplate注入到Spring的容器中,SpringBoot中支持的容器注入方式如下

@Configuration
public class BeanConfiguration{
	@Bean
	public RestTemplate getRestTemplate(){
		return new RestTemplate();
	}
}

  建立一个用来测试的接口类,并且增加两个接口,

@RestController
public class HouseController {

    @GetMapping("/house/data")
    public HouseInfo getData(@RequestParam(name = "name") String name){
        return new HouseInfo(1L,"北京","朝阳","花园小区");
    }

    @GetMapping("/house/data/{name}")
    public String getName(@PathVariable(name = "name")String name){
        return name;
    }
}

  建立一个用来调用该接口的类

@RestController
public class HouseClientController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/call/data")
    public HouseInfo getData(@RequestParam("name") String name){
        return restTemplate.getForObject("http://localhost:8081/house/data?name="+name,HouseInfo.class);
    }

    @GetMapping("/call/data/{name}")
    public String getData2(@PathVariable("name") String name){
        return restTemplate.getForObject("http://localhost:8081/house/data/{name}",String.class,name);
    }

}

  获取数据的方式通过getForObject方法来进行,这个方法有如下的三个重载方法

  • url: 请求的API地址,有两种方式,一种是url字符串,一种是通过URI的方式
  • responseType: 表示返回值类型
  • uriVariables: PathVariable 参数,有两种参数,一种是可变参数,一种是通过Map的方式进行
	@Override
	@Nullable
	public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException {
		RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
		HttpMessageConverterExtractor<T> responseExtractor =
				new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
		return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
	}

	@Override
	@Nullable
	public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException {
		RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
		HttpMessageConverterExtractor<T> responseExtractor =
				new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
		return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
	}

	@Override
	@Nullable
	public <T> T getForObject(URI url, Class<T> responseType) throws RestClientException {
		RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
		HttpMessageConverterExtractor<T> responseExtractor =
				new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
		return execute(url, HttpMethod.GET, requestCallback, responseExtractor);
	}

  当然除了使用上面这种方法,还可以用getForEntity的方式进行操作。

    @GetMapping("/call/dataEntity")
    public HouseInfo getData(@RequestParam("name") String name){
        ResponseEntity<HouseInfo> entity = restTemplate.getForEntity("http://localhost:8080/house/data?name=" + name, HouseInfo.class);
        if (entity.getStatusCodeValue()==200){
            return entity.getBody();
        }
        return null;
    }

  getForEntity方法可以获取到返回状态,请求头信息等等,通过getBody获取到响应的内容,其他的都是与getForObject是相同的也是有三种实现重载的方式。

Post方式

  在上述的代码中加入如下的的一个操作方法

    @PostMapping("/house/save")
    public Long addData(@RequestBody HouseInfo houseInfo){
        System.out.println(houseInfo.getCity());
        return 10001L;
    }

  在调用接口中编写如下的操作类使用postForObject()

    @GetMapping("/call/add")
    public Long add(){
    
        HouseInfo houseInfo = new HouseInfo();
        return restTemplate.postForObject("http://localhost:8080/call/add",houseInfo,Long.class);
        
    }

  当然postForObject方法也有如下的三种重载方法

	@Override
	@Nullable
	public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType,
			Object... uriVariables) throws RestClientException {

		RequestCallback requestCallback = httpEntityCallback(request, responseType);
		HttpMessageConverterExtractor<T> responseExtractor =
				new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
		return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
	}

	@Override
	@Nullable
	public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType,
			Map<String, ?> uriVariables) throws RestClientException {

		RequestCallback requestCallback = httpEntityCallback(request, responseType);
		HttpMessageConverterExtractor<T> responseExtractor =
				new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
		return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
	}

	@Override
	@Nullable
	public <T> T postForObject(URI url, @Nullable Object request, Class<T> responseType)
			throws RestClientException {

		RequestCallback requestCallback = httpEntityCallback(request, responseType);
		HttpMessageConverterExtractor<T> responseExtractor =
				new HttpMessageConverterExtractor<>(responseType, getMessageConverters());
		return execute(url, HttpMethod.POST, requestCallback, responseExtractor);
	}

  除了get和Post方法,RestTemplate还提供了PUT ,DELETE等操作方法,当然还有一个所有请求都可以发送的方法就是exchange方法。

总结

  这篇博客中主要介绍了在Spring 中RestTemplate的使用,当然在实际开发中通过这种方式可以有效的化简在使用Ribbon的时候进行的调用方式,能更好的整合Ribbon。简化了开发的步骤,提高开发效率

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nihui123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值