聲明式服務調用:Spring Cloud Feign
一、Feign、Ribbon、Hystrix
1.基本介紹
- 前面使用Spring Cloud Ribbon和Spring Cloud Hystrix,實現了申請活動服務中申請完活動後調用郵件服務發送郵件的功能,以此實踐了客戶端負載均衡的服務調用和通過斷路器保護微服務應用。
- 在實踐過程中,這兩個框架幾乎同時出現和使用,並且用起來比較麻煩。Spring Cloud Feign就是Ribbon和Hystrix更高層次的封裝。
- Feign基於Netflix Feign實現,整合了Spring Cloud Ribbon和Spring Cloud Hystrix,即我們可以不再使用Ribbon和Hystrix而直接使用Feign以簡化開發。
- Feign除了提供Ribbon和Hystrix兩者強大的功能外,它該提供了一種聲明式的Web服務客戶端定義方式。
2.調用其他服務方式的改變
- 使用Ribbon調用其他服務:
之前使用Ribbon調用其他服務是使用restTemplate發送請求,不太友好:
restTemplate.getForEntity("http://SCLOUD-EMAIL-SERVICE/api/email/simple/[email protected]&subject=活動申請&content=aa", String.class).getBody();
-
使用Feign調用其他服務:
使用Feign時,創建一個接口(Interface)並配置它指向郵件服務,再在這個接口中聲明方法並配置指向郵件服務的某個Restful Api接口。在活動申請服務中調用接口名.方法名就能調用到郵件服務 -
Feign只需定義服務綁定接口,以聲明的方法,優雅而簡單的實現了服務調用。
二、簡單使用Feign
1.要實現的功能
2.郵件服務編寫發送郵件的Restful Api
// 郵件服務
@RestController
@RequestMapping("/api/email")
public class EmailSendController {
// 發送郵件服務
@GetMapping(value = "/send")
public String sendEmail(){
System.out.println("郵件服務-發送郵件");
return "send ok";
}
}
3.活動申請服務添加依賴
pom.xml中添加Feign依賴
<!--Feign依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
4.啓用Feign
添加@EnableFeignClients註解
@EnableEurekaClient
@EnableFeignClients
@SpringBootApplication
public class ActivimanageApplication {
public static void main(String[] args) {
SpringApplication.run(ActivimanageApplication.class, args);
}
}
5.定義接口並配置指向郵件服務的發送郵件接口
@FeignClient中填寫郵件服務的服務名
// 配置該接口指向郵件服務
@FeignClient(value = "SCLOUD-EMAIL-SERVICE")
public interface EmailFeign {
// 配置該方法指向郵件服務的發送郵件API
@RequestMapping("/api/email/send")
String sendEmail();
}
這樣配置完成後調用 EmailFeign.sendEmail()即可相當於發送 [郵件服務/api/email/send] 這個請求。
6.在活動申請服務中使用Feign調用郵件服務
// 活動申請服務
@RestController
@RequestMapping("/api/activity")
public class ActivityApplyController {
@Autowired
private ActivityApplyService service;
// 申請活動接口
@GetMapping(value = "/simple/apply")
public void applySimpleActivity(){
// 調用Service層執行申請活動的邏輯
String emailServiceRs = service.applyActivi();
return emailServiceRs;
}
}
Service層
@Service
public class ActivityApplyService {
@Autowired
private EmailFeign emailFeign;
public String applyActivi(){
System.out.println("申請活動...");
// 使用Feign調用郵件服務
String rs = emailFeign.sendEmail();
return rs ;
}
}
7.使用
訪問活動申請服務的活動申請接口,正確返回了郵件服務的結果
三、Feign的負載均衡
上面實現了使用Feign進行遠程服務調用,再看一下它的負載均衡。
1.啓動兩個郵件服務
- 郵件服務節點1配置文件, 啓動在8003端口
server:
port: 8003
spring:
application:
name: SCLOUD-EMAIL-SERVICE # 郵件服務名
# Eureka配置
eureka:
client:
service-url:
defaultZone: http://peer1:9091/eureka/,http://peer2:9092/eureka/,http://peer3:9093/eureka/ # 指定註冊中心地址
- 郵件服務節點2配置文件, 啓動在8004端口
server:
port: 8004
spring:
application:
name: SCLOUD-EMAIL-SERVICE # 郵件服務名
# Eureka配置
eureka:
client:
service-url:
defaultZone: http://peer1:9091/eureka/,http://peer2:9092/eureka/,http://peer3:9093/eureka/ # 指定註冊中心地址
- 啓動兩個郵件服務
2.多次調用申請活動接口,查看郵件服務被調用情況
發現它是被輪詢調用的。
3.總結
- Feign實現的服務調用,依然是利用Ribbon,定時向Eurek註冊中心查詢服務列表,維護了一個郵件服務的列表,輪詢進行調用實現了負載均衡。具體如何工作的前面Ribbon那篇博客有一個圖。
四、使用Feign進行復雜接口的跨服務調用
以上是較簡單接口的跨服務調用,實際開發過程中,我們會遇到各種複雜的接口。
1.郵件服務新增三個接口
新增一個郵件實體
@Data
public class Email {
/** 收件人 */
private String to;
/** 郵件內容 */
private String content;
/** 發送結果 */
private String rs;
}
新增三個接口,基本涵蓋了我們日常開發中用到的
// 郵件服務
@RestController
@RequestMapping("/api/email")
public class EmailSendController {
// GET發送郵件:參數爲[郵件信息字符串] 返回郵件實體
@PostMapping(value = "/send/dto/re/dto")
public Email emailPostDtoReDto(@RequestParam("to") String to, @RequestParam("content") String content){
Email email = new Email();
email.setTo(to);
email.setContent(content);
email.setRs("send ok!");
return email;
}
// POST發送郵件:參數爲[郵件信息實體] 返回郵件實體
@PostMapping(value = "/send/dto/re/dto")
public Email emailPostDtoReDto(@RequestBody Email email){
email.setRs("send ok!");
return email;
}
// POST發送郵件:參數爲[郵件信息實體] 返回字符串
@PostMapping(value = "/send/dto/re/str")
public String emailPostDtoReStr(@RequestBody Email email){
return "send ok";
}
}