spring cloud的Netflix中提供了两个组件实现软负载均衡调用:ribbon和feign。本例主要讲解feign的适用,如需了解ribbon的适用,可以返回上一章进行阅读。
Ribbon
是一个基于 HTTP 和 TCP 客户端的负载均衡器
它可以在客户端配置 ribbonServerList(服务端列表),然后轮询请求以实现均衡负载。
Feign
Spring Cloud Netflix 的微服务都是以 HTTP 接口的形式暴露的,所以可以用 Apache 的 HttpClient 或 Spring 的 RestTemplate 去调用,而 Feign 是一个使用起来更加方便的 HTTP 客戶端,使用起来就像是调用自身工程的方法,而感觉不到是调用远程方法。
spring-cloud-starter-feign 里面已经包含了 spring-cloud-starter-ribbon(Feign 中也使用了 Ribbon)
一、pom引入
-
<!--feign相关--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> <!-- Ribbon相关 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <!--Ribbon相关end-->
二、配置文件application.yml编写(和上一章ribbon的编写相同)
-
server: port: 8080 #从eureka中获取微服务 eureka: client: register-with-eureka: false service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
三、接口DeptClientService编写,为了考虑复用性,卸载了公共模块api中
-
package com.zhanghf.springcloud.service; import com.zhanghf.springcloud.entities.Dept; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import java.util.List; /** * @Description: 修改microservicecloud-api工程,根据已经有的DeptClientService接口 * Created by YQ11053 on 2018/10/5 0005. */ @FeignClient(value = "MICROSERVICECLOUD-DEPT") public interface DeptClientService { @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET) public Dept get(@PathVariable("id") long id); @RequestMapping(value = "/dept/list", method = RequestMethod.GET) public List<Dept> list(); @RequestMapping(value = "/dept/add", method = RequestMethod.POST) public boolean add(Dept dept); }
使用FeignClient注解,value为微服务提供者的名称,需要和微服务提供者配置类appiication.yml中的命名一样。
四、controller中
-
package com.zhanghf.springcloud.controller; import com.zhanghf.springcloud.entities.Dept; import com.zhanghf.springcloud.service.DeptClientService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * Created by YQ11053 on 2018/9/26 0026. */ @RestController public class DeptController_Consumer { @Autowired DeptClientService deptClientService; @RequestMapping(value = "/consumer/dept/add") public boolean add(Dept dept) { return deptClientService.add(dept); } @RequestMapping(value = "/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id) { return deptClientService.get(id); } @SuppressWarnings("unchecked") @RequestMapping(value = "/consumer/dept/list") public List<Dept> list() { return deptClientService.list(); } }
特此贴出使用ribbon的时候的controller中代码如下:
-
package com.zhanghf.springcloud.controller; import com.zhanghf.springcloud.entities.Dept; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import java.util.List; /** * Created by YQ11053 on 2018/9/26 0026. */ @RestController public class DeptController_Consumer { // private static final String REST_URL_PREFIX = "http://localhost:8001"; private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT"; @Autowired private RestTemplate restTemplate; @RequestMapping(value = "/consumer/dept/add") public boolean add(Dept dept) { return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class); } @RequestMapping(value = "/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id) { return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class); } @SuppressWarnings("unchecked") @RequestMapping(value = "/consumer/dept/list") public List<Dept> list() { return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class); } // 测试@EnableDiscoveryClient,消费端可以调用服务发现 @RequestMapping(value = "/consumer/dept/discovery") public Object discovery() { return restTemplate.getForObject(REST_URL_PREFIX + "/dept/discovery", Object.class); } }
使用feign时通过注入deptClientService来进行各种方法的调用,其余工作都在接口中实现,而ribbon是通过RestTemplate 类实现。
五、启动类
-
package com.zhanghf; import com.myrule.MySelfRule; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.feign.EnableFeignClients; import org.springframework.cloud.netflix.ribbon.RibbonClient; import org.springframework.context.annotation.ComponentScan; @SpringBootApplication @EnableEurekaClient @EnableFeignClients(basePackages= {"com.zhanghf.springcloud"}) @ComponentScan("com.zhanghf.springcloud") public class DeptConsumer80_Feign { public static void main( String[] args ) { SpringApplication.run(DeptConsumer80_Feign.class,args); } }
如果也需要进行负载均衡策略的调整或者自定义的话使用方法如上一章ribbon的介绍。