Ribbon RestTemplate和Feign调用比较

一、服务调用几种方式

  1. Httpclient
    使用HttpClient发送请求主要分为以下几步骤:

     创建 CloseableHttpClient对象或CloseableHttpAsyncClient对象,前者同步,后者为异步
     创建Http请求对象
     调用execute方法执行请求,如果是异步请求在执行之前需调用start方法
    
  2. Okhttp
    使用OkHttp发送请求主要分为以下几步骤:

     创建OkHttpClient对象
     创建Request对象
     将Request 对象封装为Call
     通过Call 来执行同步或异步请求,调用execute方法同步执行,调用enqueue方法异步执行
    
  3. HttpURLConnection
    HttpURLconnection是基于http协议的,支持get,post,put,delete等各种请求方式,最常用的就是get和post

  4. RestTemplate
    RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。

二、Ribbon+RestTemplate

配置一个eureka server注册中心,创建一个springboot项目
添加依赖

    
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-server
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        
    

    
        
            
                org.springframework.cloud
                spring-cloud-dependencies
                ${spring-cloud.version}
                pom
                import
            
        
    

application.properties配置文件

server.port=8761

eureka.instance.hostname=localhost
eureka:
    client:
        registerWithEureka: false
        fetchRegistry: false
        serviceUrl:
            defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

启动类EurekaServerApplication

package com.boss.springcloud.eurekaserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }

}

创建一个服务提供者 (eureka client),新建一个spring boot项目,通过改变端口号运行多个提供者
添加依赖

    
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        
        
            org.springframework.boot
            spring-boot-starter-web
            2.2.1.RELEASE
            compile
        
    

    
        
            
                org.springframework.cloud
                spring-cloud-dependencies
                ${spring-cloud.version}
                pom
                import
            
        
    

application.properties配置文件

eureka:
    client:
    serviceUrl:
        defaultZone: http://localhost:8761/eureka/
server.port=8764

spring.application.name=service-hi

启动类SpringClientApplication

package com.boss.springcloud.springclient;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@EnableEurekaClient
@RestController
public class SpringClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringClientApplication.class, args);
    }

    @Value("${server.port}")
    String port;
    @RequestMapping("/hi")
    public String home(@RequestParam String name) {
        return "hi "+name+",i am from port:" +port;
    }

}

ribbon+restTemplate配置一个服务消费者
添加依赖


        
            org.springframework.cloud
            spring-cloud-starter-netflix-hystrix
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-hystrix-dashboard
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-ribbon
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        
    

    
        
            
                org.springframework.cloud
                spring-cloud-dependencies
                ${spring-cloud.version}
                pom
                import
            
        
    

application.properties配置文件

eureka:
    client:
        serviceUrl:
            defaultZone: http://localhost:8761/eureka/
server.port=8768
spring.application.name=service-ribbon

ServiceRibbonApplication 启动类

package com.boss.springcloud.serviceribbon;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableHystrix
@EnableHystrixDashboard
@EnableDiscoveryClient
@SpringBootApplication
public class ServiceRibbonApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServiceRibbonApplication.class, args);
    }

    @Bean
    @LoadBalanced
    RestTemplate restTemplate(){
        return new RestTemplate();
    }

    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}

controller

package com.boss.springcloud.serviceribbon.controller;

import com.boss.springcloud.serviceribbon.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HiController {
    @Autowired
    HelloService helloService;

    @RequestMapping("/hi")
    public String hi(@RequestParam String name){
        return helloService.hiService(name);
    }
}

service

package com.boss.springcloud.serviceribbon.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class HelloService {
    @Autowired
    RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "hiError")
    public String hiService(String name){
        return restTemplate.getForObject("http://service-hi/hi?name="+name,String.class);
    }
    public String hiError(String name){
        return "hi,"+name+",sorry,error";
    }
}

访问eurake中心可以看到注册的服务
Ribbon RestTemplate和Feign调用比较_第1张图片
访问网址http://localhost:8768/hi?name=zzz,它会依次调用两个服务提供者,实现负载均衡
Ribbon RestTemplate和Feign调用比较_第2张图片
Ribbon RestTemplate和Feign调用比较_第3张图片

三、Feign

注册中心和生产者可以延续上面的,新建一个spring boot项目创建由feign实现的消费者
pom依赖


            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        
        
            org.springframework.cloud
            spring-cloud-starter-openfeign
        

配置文件

eureka:
    client:
        serviceUrl:
            defaultZone: http://localhost:8761/eureka/
server.port=8769
spring.application.name=service-feign

启动类

package com.boss.springcloud.feign;

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
@EnableFeignClients
@EnableEurekaClient
public class FeignApplication {

    public static void main(String[] args) {
        SpringApplication.run(FeignApplication.class, args);
    }

}

controller层

package com.boss.springcloud.feign.controller;

import com.boss.springcloud.feign.serivce.FeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FeignController {

    @Autowired
    FeignService feignService;

    @ResponseBody
    @RequestMapping(value="/feign")
    public String hi(@RequestParam String name){
        return feignService.getService(name);
    }
}

service层,接口,调用生产者的方法

package com.boss.springcloud.feign.serivce;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Component
@FeignClient("service-hi") //生产者的名称spring.application.name
public interface FeignService {
    @ResponseBody
    @RequestMapping(value="/hi") //生产者方法的地址
    public String getService(@RequestParam String name);
}

eureka注册中心
Ribbon RestTemplate和Feign调用比较_第4张图片
访问http://localhost:8769/feign?name=zzz,会循环出现以下两者结果
Ribbon RestTemplate和Feign调用比较_第5张图片
在这里插入图片描述

四、总结

FeignClient简化了请求的编写,且通过动态负载进行选择要使用哪个服务进行消费,而这一切都由Spring动态配置实现,我们不用关心这些,只管使用方法即可。而restTemplate需要我们自定义一个RestTemplate,手动注入。但是resttemplate有一个feign没有的功能,那就是他可以条用微服务集群外的服务,因为他可以通过ip去调用。

你可能感兴趣的:(Ribbon RestTemplate和Feign调用比较)