好久沒更新了,由于工作雜事比較多,時間比較瑣碎渠抹,所以學(xué)習(xí)記錄延遲更新了。話不多說闪萄,讓我們言歸正傳梧却。
基礎(chǔ)內(nèi)容
Declarative REST Client: Feign (聲明式REST服務(wù)調(diào)用)
通過spring官方文檔可以了解到,F(xiàn)eign是一個聲明式web 服務(wù)調(diào)用服務(wù)桃煎,他使得一切web服務(wù)得以簡化篮幢。我們只需要創(chuàng)建一個接口并用注解和JAX-RS注解的方式來配置它,即可完成對服務(wù)提供方的接口綁定为迈。
遠程過程調(diào)用協(xié)議(RPC)
RPC(Remote Procedure Call)—遠程過程調(diào)用三椿,它是一種通過網(wǎng)絡(luò)從遠程計算機程序上請求服務(wù),而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議葫辐。RPC協(xié)議假定某些傳輸協(xié)議的存在搜锰,如TCP或UDP,為通信程序之間攜帶信息數(shù)據(jù)耿战。在OSI網(wǎng)絡(luò)通信模型中蛋叼,RPC跨越了傳輸層和應(yīng)用層。RPC使得開發(fā)包括網(wǎng)絡(luò)分布式多程序在內(nèi)的應(yīng)用程序更加容易剂陡。 ----- 百度百科
RPC代表
- JAVA RMI (二進制協(xié)議)
- WebService (文本協(xié)議)
消息傳遞
? RPC是一種請求-響應(yīng)協(xié)議狈涮,一次RPC在客戶端初始化,再由客戶端將請求消息傳遞到遠程的服務(wù)端鸭栖,執(zhí)行指定的帶有參數(shù)的過程歌馍。經(jīng)過遠程服務(wù)端執(zhí)行過后,將結(jié)果作為響應(yīng)內(nèi)容返回到客戶端晕鹊。
存根
在一次分布式計算RPC中松却,客戶端和服務(wù)端轉(zhuǎn)換參數(shù)的一段代碼,由于存根的參數(shù)轉(zhuǎn)化溅话,RPC執(zhí)行過程如同本地執(zhí)行函數(shù)調(diào)用晓锻。存根必須在客戶端和服務(wù)端兩端均裝載,并且必須保持兼容飞几。
簡單實現(xiàn)Feign整合?
1.流程圖
我們可以看到砚哆,客戶端通過調(diào)用一定的Feign協(xié)議就可以實現(xiàn)請求和響應(yīng)。接下來讓我們來手動操作一下屑墨,感受一下Feign的奇妙吧窟社。
2.搭建環(huán)境并整合Feign
我們還是老規(guī)矩,基于上一套的環(huán)境基礎(chǔ)上來開發(fā)绪钥,如果同學(xué)不會搭建之前的環(huán)境灿里,可以看這篇文章--Spring Cloud系列--簡單實現(xiàn)Ribbon負載均衡,很簡單就搭建起來了(如果時間充裕程腹,可以先將Spring Cloud系列--簡單實現(xiàn)Hystrix熔斷器 實現(xiàn)一下)匣吊。
a.注冊中心
? 注冊中心不需要做任何改動,按照之前的文章搭建即可寸潦。
b.客戶端(myribbon)
首先在pom.xml文件中色鸳,增加相關(guān)依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
由于是整合Feign,那么我們在路徑com.consumer.myribbon
下創(chuàng)建一個包名為feign
见转。
(1)首先定義一個存根(上面有講到) ,這個存根很重要命雀,在服務(wù)端和客戶端都需要有。
/**
* @ClassName Student
* @Description DTO
* @Author Neal
* @Date 2019/4/29 14:40
* @Version 1.0
*/
public class Student {
private String name;
private String id;
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", id='" + id + '\'' +
'}';
}
}
(2)定義Feign API
/**
* @ClassName StudentService
* @Description feign API接口
* @Author Neal
* @Date 2019/4/29 14:36
* @Version 1.0
*/
//服務(wù)端ID,我們的服務(wù)端斩箫,也就是provider項目的項目ID就是RIBBON-SERVICE
//下面有提及
@FeignClient(name = "RIBBON-SERVICE")
public interface StudentService {
/**
* 獲取所有學(xué)生列表
* @return
*/
@GetMapping(value = "/myfeign/student")
String getAllStudent();
/**
* 添加學(xué)生
* @param student
* @return
*/
@PostMapping(value = "/myfeign/student")
String saveStudent(@RequestBody Student student);
}
(3)創(chuàng)建一個controller 實現(xiàn)對feign的調(diào)用
/**
* @ClassName StudentController
* @Description 對feign的調(diào)用
* @Author Neal
* @Date 2019/4/29 14:47
* @Version 1.0
*/
@RestController
public class StudentController implements StudentService{
@Autowired
private StudentService studentService;
@Override
public String getAllStudent() {
return studentService.getAllStudent();
}
@Override
public String saveStudent(Student student) {
return studentService.saveStudent(student);
}
}
(4) 開啟feign的支持
? 我們在啟動引導(dǎo)類中添加@EnableFeignClients
注解吏砂。
@EnableEurekaClient
@SpringBootApplication
@EnableFeignClients(clients = StudentService.class) //指定API開啟
public class MyribbonApplication {
public static void main(String[] args) {
SpringApplication.run(MyribbonApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
最終目錄如下:
我們客戶端的修改已經(jīng)完成撵儿,看看是不是很簡單。
c.服務(wù)端(provider)
(1) 在路徑com.consumer.myribbon
下創(chuàng)建 包名為 feign
的文件夾狐血。并將存根(Student.java
) 以及 Feign協(xié)議(StudentService.java
)放入包下淀歇。這里需要注意一下,我們在服務(wù)端的話匈织,就不需要標(biāo)注@FeignClient
注解了浪默。
/**
* @ClassName StudentService
* @Description feign API接口
* @Author Neal
* @Date 2019/4/29 14:36
* @Version 1.0
*/
public interface StudentService {
@GetMapping(value = "/myfeign/student")
String getAllStudent();
@PostMapping(value = "/myfeign/student")
String saveStudent(@RequestBody Student student);
}
(2) 實現(xiàn)StudentService
接口,這里就簡單的使用內(nèi)存來模擬數(shù)據(jù)庫存儲。
/**
* @ClassName StudentServiceImp
* @Description StudentService實現(xiàn)類
* @Author Neal
* @Date 2019/4/29 17:10
* @Version 1.0
*/
@Service("iStudentServiceImp")
public class StudentServiceImp implements StudentService {
private static List<Student> studentList = new ArrayList<>();
@Override
public String getAllStudent() {
return studentList.toString();
}
@Override
public String saveStudent(Student student) {
studentList.add(student);
return "ok";
}
}
(3) 服務(wù)端的調(diào)用controller
/**
* @ClassName StudentController
* @Description TODO
* @Author Neal
* @Date 2019/4/29 14:58
* @Version 1.0
*/
@RestController
public class StudentController implements StudentService{
@Autowired
@Qualifier("iStudentServiceImp")
StudentService studentService;
@Override
public String getAllStudent() {
return studentService.getAllStudent();
}
@Override
public String saveStudent(Student student) {
return studentService.saveStudent(student);
}
}
(4) 啟動類不變
最終的文件目錄如下:
3.啟動測試
首先我們啟動這三個項目缀匕,啟動順序是 spring-cloud-test-register -> provider -> myribbon
a.啟動完成后纳决,查看 http://localhost:1111/ 注冊中心信息
b.如果如上圖所示,則表示注冊成功乡小。接下來讓我們測試Feign API接口阔加。
saveStudent接口測試
打開postman 輸入相應(yīng)的參數(shù)并發(fā)送。
設(shè)置參數(shù):
發(fā)送請求劲件,并查看結(jié)果
通過圖中掸哑,我們可以看到請求響應(yīng)的時間略長,具體原因抽時間去排查一下零远。
getAllStudent接口測試
輸入url查看結(jié)果即可
總結(jié)
? 基礎(chǔ)的Feign 整合已經(jīng)搞完了苗分,是不是很簡單,其實spring-cloud的強大牵辣,真的是越學(xué)越覺得恐怖摔癣,感謝巨人們的付出。之后會將熔斷也整合進來纬向,這樣就是個比較完整的請求生態(tài)了择浊。