服务发现与调用——Ribbon与Feign
Ribbion简介
Ribbon 带有负载均衡功能
Fegin实现基于Ribbon
代码实现步骤
pom.xml中引入eureka-server和netfix-ribbon依赖
application.yml中指定配置项,端口、application name、eureka-server地址
SpringBoot 启动类添加注解@EnableEurekaClient @EnableDiscoveryClient
使用@Bean @LoadBalanced向Spring容器注入org.springframework.web.client.RestTemplate 实例
在使用之处使用@Autowired public RestTemplate restTemplate; 获取实例,调用服务提供方提供的方法
关键代码
@EnableEurekaClient
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaServiceRibbonApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(EurekaServiceRibbonApplication.class, args);
}
}
也可以configApplication使用
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
service
其中http://eureka-service//print为其他服务接口 如果这个eureka-service有多个不同端口实例,就会自动负载均衡,还可以加上ip,指定实例
package org.oscar.scd.eureka.service.ribbon.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class HelloRibbonService {
@Autowired
public RestTemplate restTemplate;
public String hiService(String name) {
return restTemplate.getForObject("http://eureka-service//print?name=" + name, String.class);
}
}
Controller
import org.oscar.scd.eureka.service.ribbon.service.HelloRibbonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/ribbon")
public class HelloRibbonController {
@Autowired
public HelloRibbonService service;
@GetMapping("/print")
public String print(@RequestParam String name) {
return this.service.hiService(name);
}
这里在Controller中补充介绍三种数据传输方式
第三种便是上面介绍的,常用方式。
//第二种方式
@Autowired
private LoadBalancerClient loadBalancerClient;
//第三种方式
@Autowired
private RestTemplate restTemplate;
/**
* 第一种方式 通过url
* @return
*/
@RequestMapping("/one")
public String one(){
RestTemplate restTemplate =new RestTemplate();
String response = restTemplate.getForObject("http://localhost:8773/one",String.class);
System.out.println(response);
return response;
}
@RequestMapping("/two")
public String two(){
ServiceInstance serviceInstance =loadBalancerClient.choose("one");//为null
serviceInstance.getHost();
String url = String.format("http://%s:%s",serviceInstance.getHost(),serviceInstance.getPort()+"/msg");
String response = restTemplate.getForObject(url,String.class);
return response;
}
@RequestMapping("/three")
public String three(){
String response = restTemplate.getForObject("http://one/one",String.class);
return response;
}
//对象测试
@RequestMapping("four")
public Goods four(){
Goods goods =restTemplate.getForObject("http://one/two",Goods.class);//对象服务两边都要有
System.out.println(goods);
return goods;
}
Feign介绍
Feign 是一个声明式调用HTTP协议服务的客户端
支持注解形式发现与调用服务
支持编码与解码
与Ribbon、Eureka结合使用可实现负载均衡功能
代码实现步骤
pom.xml中引入spring-cloud-starter-netflix-eureka-server和spring-cloud-starter-openfeign依赖
application.yml中指定配置项,端口、application.name、eureka-server地址
SpringBoot 启动类添加启用Fegin的注解@EnableFeignClients
在当前项目Service接口类名上使用FeignClient注解指定服务提供者的服务名@FeignClient(“eureka-service”)
在需要调用服务提供者的接口方法之上使用注解指定调用服务提供者提供的方法@RequestMapping("/print")
在需要使用服务提供者提供的方法之处,使用第4步与第5步实例化好的服务提供者的方法
关键代码
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients
@EnableEurekaClient
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaServiceFeignApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServiceFeignApplication.class, args);
}
}
service(注意与上面的不同)
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient("eureka-service")
public interface FeignHelloService {
@RequestMapping("/print")
String printPort(@RequestParam("name") String name);
}
controller
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
@RequestMapping("/feign")
public class FeignHelloController {
@Autowired
private FeignHelloService service;
@RequestMapping("/print")
public String print(@RequestParam("name") String name) {
return this.service.printPort(name);
}
}
feign开启熔断器
注意feign里面开启熔断器处理时,需要有以下配置:
spring:
application:
name: service-feign
hystrix:
enabled: true
client:
service-url:
defaultZone:
熔断器的配置就拿一个订单的熔断器来说,需要继承相应的订单feign接口,并且在注解里面的@feignclient里面申明到fallback会调用到订单的熔断器类。
@FeignClient(name = "total-service",fallback = OrderHystrics.class)
public interface OrderFeignClient {
public static final String version="/v0/order/";
@RequestMapping(value =version+"sending/order/batch")
@ApiOperation(value = "获取用户所有的发货中订单内容",notes = "获取用户所有订单内容")
@ApiImplicitParams({
@ApiImplicitParam(name = "sessionKey", value = "sessionKey", dataType = "String",paramType = "query"),
@ApiImplicitParam(name = "page",value = "pageNum",dataType = "int",paramType = "query") })
public List<Object> sendingOrder(@RequestParam(name = "sessionKey") String sessionKey,
@RequestParam(name = "page") int page);
}
熔断器部分代码:
@Component
@Slf4j
public class OrderHystrics implements OrderFeignClient {
public List<Object> sendingOrder(String sessionKey, int page) {
Date date=new Date();
log.warn(date.toString()+"sendingOrder出现异常!请管理员尽快处理");
return null;
}
}
写到最后
根据上述内容可以了解负载均衡之feign与ribbon比较,选择feign
理由:1. feign本身里面就包含有了ribbon
2. feign自身是一个声明式的伪http客户端,写起来更加思路清晰和方便
3. fegin是一个采用基于接口的注解的编程方式,更加简便