springboot中使用Feign整合nacos,gateway進(jìn)行微服務(wù)之間的調(diào)用方法
1、什么是Feign
Feign 是 Spring Cloud Netflix 組件中的一個(gè)輕量級(jí) RESTful 的 HTTP 服務(wù)客戶端,實(shí)現(xiàn)了負(fù)載均衡和 Rest 調(diào)用的開源框架,封裝了 Ribbon 和 RestTemplate,實(shí)現(xiàn)了 WebService 的面向接口編程,進(jìn)一步降低了項(xiàng)目的耦合度。
Feign 內(nèi)置了 Ribbon(其主要功能是提供客戶端實(shí)現(xiàn)負(fù)載均衡算法),用來做客戶端負(fù)載均衡調(diào)用服務(wù)注冊(cè)中心的服務(wù)。
Feign 本身并不支持 Spring MVC 的注解,它有一套自己的注解,為了更方便的使用,Spring Cloud 孵化了 OpenFeign。
Feign 是一種聲明式、模板化的 HTTP 客戶端(僅在 Consumer 中使用)。
Feign 支持的注解和用法請(qǐng)參考官方文檔:https://github.com/OpenFeign/feign 或 spring.io 官網(wǎng)文檔
Feign 的使用方式是:使用 Feign 的注解定義接口,調(diào)用這個(gè)接口,就可以調(diào)用服務(wù)注冊(cè)中心的服務(wù)。
2、為什么使用Feign?
1.微服務(wù)之間調(diào)用變得簡(jiǎn)單
它讓微服務(wù)之間的調(diào)用變得更簡(jiǎn)單了,類似controller調(diào)用service
2.使用簡(jiǎn)單
只需要?jiǎng)?chuàng)建一個(gè)接口,然后添加注解即可使用Feign
3.簡(jiǎn)化代碼
Feign默認(rèn)集成了Ribbon,簡(jiǎn)化了使用Spring Cloud Ribbon負(fù)載均衡時(shí),自動(dòng)封裝服務(wù)調(diào)用客戶端的開發(fā)量
3、如何使用Feign?
目錄及項(xiàng)目結(jié)構(gòu)
子工程
<modules> <module>service-provider</module> <module>service-provider02</module> <module>service-consumer</module> <module>service-gateway</module> </modules>
注:
注冊(cè)中心實(shí)例 nacos
service-provider | service-provider02 服務(wù)提供者實(shí)例
service-consumer 服務(wù)消費(fèi)者
service-gateway 網(wǎng)關(guān)服務(wù)
3.1注冊(cè)中心Nacos部署
部署nacos(略)
3.2部署生產(chǎn)者
1.新建maven項(xiàng)目,過程省略…
2.關(guān)鍵配置
server: port: 7070 # 端口 spring: application: name: service-provider # 應(yīng)用名稱(集群下相同) #nacos配置 spring: cloud: nacos: discovery: server-addr: localhost:8848
3.邏輯部分
為了檢測(cè)Feign的負(fù)載均衡,所以在provide01中,將返回結(jié)果增加01后綴
/** * 查詢商品列表 * * @return */ @Override public List<Product> selectProductList() { return Arrays.asList( new Product(1, "華為手機(jī)01", 1, 5800D), new Product(2, "聯(lián)想筆記本01", 1, 6888D), new Product(3, "小米平板01", 5, 2020D) ); }
4.部署雙節(jié)點(diǎn)provide02
重復(fù)步驟 【1~3】,修改serverImpl邏輯,改為后綴加02
/** * 查詢商品列表 * * @return */ @Override public List<Product> selectProductList() { return Arrays.asList( new Product(1, "華為手機(jī)02", 1, 5800D), new Product(2, "聯(lián)想筆記本02", 1, 6888D), new Product(3, "小米平板02", 5, 2020D) ); }
5.啟動(dòng)雙節(jié)點(diǎn),監(jiān)控Nacos
3.3 部署消費(fèi)者,使用Feign調(diào)用provider方法
1.新建maven工程,過程省略…
2.引入nacos和feign的pom依賴
<!-- nacos 依賴 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>0.9.0.RELEASE</version> </dependency><!-- spring cloud openfeign 依賴 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
3.添加配置文件
server: port: 9090 # 端口 spring: application: name: service-consumer # 應(yīng)用名稱 spring: cloud: nacos: discovery: server-addr: localhost:8848
4.在服務(wù)接口層聲明使用Feign
使用FeignClient注解,聲明要調(diào)用的服務(wù)
// 聲明需要調(diào)用的服務(wù) @FeignClient("service-provider") public interface ProductService
對(duì)方法使用GetMapping注解,配置需要調(diào)用的服務(wù)路由地址
// 配置需要調(diào)用的服務(wù)地址及參數(shù) @GetMapping("/product/list") List<Product> selectProductList();
5.方法調(diào)用
在另一個(gè)impl里調(diào)用ProductService的方法,而不用關(guān)注ProductServiceImpl里面的實(shí)現(xiàn)邏輯,它會(huì)遠(yuǎn)程請(qǐng)求生產(chǎn)者中controller里的方法.
/** * 根據(jù)主鍵查詢訂單 * * @param id * @return */ @Override public Order selectOrderById(Integer id) { return new Order(id, "order-001", "中國(guó)", 22788D, productService.selectProductList()); }
消費(fèi)者controller中的方法
/** * 根據(jù)主鍵查詢訂單 * * @param id * @return */ @GetMapping("/{id}") public Order selectOrderById(@PathVariable("id") Integer id) { return orderService.selectOrderById(id); }
過postman調(diào)用 localhost:9090/order/2 結(jié)果,可以看到已經(jīng)成功使用Feign進(jìn)行了遠(yuǎn)程調(diào)用,
并且同一個(gè)請(qǐng)求,返回兩個(gè)provider的不同結(jié)果,由此可知Feign也實(shí)現(xiàn)了負(fù)載均衡
4.ribbon負(fù)載均衡策略
在消費(fèi)者配置文件中修改ribbon的負(fù)載均衡策略
service-provider: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #配置規(guī)則 隨機(jī) # NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #配置規(guī)則 輪詢 # NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule #配置規(guī)則 重試 # NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule #配置規(guī)則 響應(yīng)時(shí)間權(quán)重 # NFLoadBalancerRuleClassName: com.netflix.loadbalancer.BestAvailableRule #配置規(guī)則 最空閑連接策略
5.Feign傳參
1.Get方法
使用 @PathVariable 注解或 @RequestParam 注解接收請(qǐng)求參數(shù)。
provider接口層ProductService.java
ProductService.java方法
/** * 根據(jù)主鍵查詢商品 * * @param id * @return */ Product selectProductById(Integer id); provider實(shí)現(xiàn)類ProductServiceImpl.java
ProductServiceImpl.java方法
/** * 根據(jù)主鍵查詢商品 * * @param id * @return */ @Override public Product selectProductById(Integer id) { return new Product(id, "冰箱", 1, 2666D); }
provider的控制類ProductController.java
ProductController.java方法
/** * 根據(jù)主鍵查詢商品 * * @param id * @return */ @GetMapping("/{id}") public Product selectProductById(@PathVariable("id") Integer id) { return productService.selectProductById(id); }
provider服務(wù)中,controller使用了(@PathVariable(“id”) Integer id) 進(jìn)行參數(shù)接收
consumer的接口層ProductService.java
@GetMapping("/product/{id}") Product selectProductById(@PathVariable("id") Integer id);
consumer服務(wù)中,使用了(@PathVariable(“id”) Integer id) 進(jìn)行參數(shù)接收,寫法類似于在controller中定義請(qǐng)求方法和定義參數(shù)
consumer的接口層OrderService.java
Order getOrderById(Integer id);
consumer的接口實(shí)現(xiàn)類OrderServiceImpl.java
@Override public Order getOrderById(Integer id) { return new Order(id, "order-003", "中國(guó)", 2666D, Arrays.asList(productService.selectProductById(id))); }
consumer的控制類OrderController.java
@GetMapping("selectProductById/{id}") public Order selectProductById(@PathVariable("id") Integer id) { return orderService.getOrderById(id); }
訪問localhost:9090/order/selectProductById/888得到結(jié)果
Post方法
使用 @RequestBody 注解接收請(qǐng)求參數(shù)。
provider的ProductService.java
/** * 新增商品 * * @param product * @return */ Map<Object, Object> createProduct(Product product);
provider的ProductServiceImpl.java
/** * 新增商品 * * @param product * @return */ @Override public Map<Object, Object> createProduct(Product product) { System.out.println(product.getProductName()); return new HashMap<Object, Object>() {{ put("code", 200); put("message", "新增成功"); }}; }
provider的ProductController.java
/** * 新增商品 * * @param product * @return */ @PostMapping("/save") public Map<Object, Object> createProduct(@RequestBody Product product) { return productService.createProduct(product); }
consumer的ProductService.java
/** * 新增商品 * * @param product * @return */ @PostMapping("/product/save") Map<Object, Object> createProduct(Product product); consumer的OrderService.java Map<Object, Object> createProduct(Product product); consumer的OrderServiceImpl.java @Override public Map<Object, Object> createProduct(Product product) { return productService.createProduct(product); }
consumer的OrderController.java
/** * 新增商品 * * @param product * @return */ @PostMapping("/save") public Map<Object, Object> createProduct(Product product) { return orderService.createProduct(product); }
訪問http://localhost:9090/order/save 參數(shù)
id:6
productName:華為
productNum:1
productPrice:6666666
執(zhí)行結(jié)果
6.Feign 性能優(yōu)化
1.Gzip 壓縮
gzip 是一種數(shù)據(jù)格式,采用 deflate 算法壓縮數(shù)據(jù);gzip 是一種流行的文件壓縮算法,應(yīng)用十分廣泛,尤其是在 Linux 平臺(tái)。
2.gzip 能力
當(dāng) Gzip 壓縮一個(gè)純文本文件時(shí),效果是非常明顯的,大約可以減少 70% 以上的文件大小。
3.gzip 作用
網(wǎng)絡(luò)數(shù)據(jù)經(jīng)過壓縮后實(shí)際上降低了網(wǎng)絡(luò)傳輸?shù)淖止?jié)數(shù),最明顯的好處就是可以加快網(wǎng)頁(yè)加載的速度。網(wǎng)頁(yè)加載速度加快的好處不言而喻,除了節(jié)省流量,改善用戶的瀏覽體驗(yàn)外,另一個(gè)潛在的好處是 Gzip 與搜索引擎的抓取工具有著更好的關(guān)系。例如 Google 就可以通過直接讀取 gzip 文件來比普通手工抓取更快地檢索網(wǎng)頁(yè)。
4.配置HTTP 連接池
4.1HTTP背景
兩臺(tái)服務(wù)器建立 HTTP 連接的過程是很復(fù)雜的一個(gè)過程,涉及到多個(gè)數(shù)據(jù)包的交換,很耗時(shí)間。
HTTP 連接需要的 3 次握手 4 次揮手開銷很大,這一開銷對(duì)于大量的比較小的 HTTP 消息來說更大。
4.2解決方案
采用 HTTP 連接池,可以節(jié)約大量的 3 次握手 4 次揮手,這樣能大大提升吞吐量。
Feign 的 HTTP 客戶端支持 3 種框架:HttpURLConnection、HttpClient、OkHttp;默認(rèn)是 HttpURLConnection。可以通過查看源碼 org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration.java 得知。
傳統(tǒng)的 HttpURLConnection 是 JDK 自帶的,并不支持連接池,如果要實(shí)現(xiàn)連接池的機(jī)制,還需要自己來管理連接對(duì)象。對(duì)于網(wǎng)絡(luò)請(qǐng)求這種底層相對(duì)復(fù)雜的操作,如果有可用的其他方案,沒有必要自己去管理連接對(duì)象。
HttpClient 相比傳統(tǒng) JDK 自帶的 HttpURLConnection,它封裝了訪問 HTTP 的請(qǐng)求頭,參數(shù),內(nèi)容體,響應(yīng)等等;它不僅使客戶端發(fā)送 HTTP 請(qǐng)求變得容易,而且也方便了開發(fā)人員測(cè)試接口(基于 HTTP 協(xié)議的),既提高了開發(fā)的效率,又提高了代碼的健壯性;另外高并發(fā)大量的請(qǐng)求網(wǎng)絡(luò)的時(shí)候,也是用“連接池”提升吞吐量。
添加依賴
<dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> <version>10.7.4</version> </dependency>
配置開啟連接池
feign: httpclient: enabled: true # 開啟 httpclient
使用壓測(cè)工具檢測(cè)單線程 10000次請(qǐng)求網(wǎng)絡(luò)響應(yīng)情況
圖1.未配置httpclient連接池.新建連接和關(guān)閉連接占用大量時(shí)間,端口被占用無法釋放.導(dǎo)致后來的連接無法被創(chuàng)建,增加程序異常幾率
圖2.配置httpClient連接池開啟,第一次交互會(huì)打開連接,交互結(jié)束后連接并不關(guān)閉,下次交互就省去了建立連接的過程
7.整合gateway網(wǎng)關(guān)服務(wù)
1.搭建gateway網(wǎng)關(guān)服務(wù)(略)
2.增加配置
server: port: 8001 #網(wǎng)關(guān)端口 spring: application: name: nacos-gateway cloud: nacos: discovery: server-addr: localhost:8848 #注冊(cè)中心地址 config: server-addr: localhost:8848 #配置中心地址 TODO配置中心讀取不到 需要調(diào)查原因 file-extension: yaml gateway: discovery: locator: enabled: true lower-case-service-id: true routes: - id: nacos-gateway-provider uri: lb://service-consumer #目標(biāo)服務(wù)地址 predicates: #斷言 - Path=/**
3.測(cè)試8001端口轉(zhuǎn)發(fā)是否正常
到此這篇關(guān)于springboot中使用Feign整合nacos,gateway進(jìn)行微服務(wù)之間的調(diào)用方法的文章就介紹到這了,更多相關(guān)springboot Feign微服務(wù)調(diào)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決使用IDEA時(shí)跳轉(zhuǎn)到.class的問題
這篇文章主要介紹了解決使用IDEA時(shí)跳轉(zhuǎn)到.class的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08SpringBoot自定義Starter實(shí)現(xiàn)流程詳解
SpringBoot中的starter是一種非常重要的機(jī)制,能夠拋棄以前繁雜的配置,將其統(tǒng)一集成進(jìn)starter,應(yīng)用者只需要在maven中引入starter依賴,SpringBoot就能自動(dòng)掃描到要加載的信息并啟動(dòng)相應(yīng)的默認(rèn)配置。starter讓我們擺脫了各種依賴庫(kù)的處理,需要配置各種信息的困擾2022-09-09elasticsearch 8.2.3 安裝及springboot簡(jiǎn)單使用
這篇文章主要介紹了elasticsearch 8.2.3 安裝及springboot簡(jiǎn)單使用,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06SpringBoot枚舉類型參數(shù)認(rèn)證的實(shí)現(xiàn)代碼
項(xiàng)目當(dāng)中經(jīng)常需要接口參數(shù)是否在一個(gè)可選的范圍內(nèi),也就是驗(yàn)證類枚舉參數(shù)的需求,所以本文我們將使用SpringBoot實(shí)現(xiàn)枚舉類型參數(shù)認(rèn)證,文中有詳細(xì)的代碼示例,需要的朋友可以參考下2023-12-12Java使用建造者模式實(shí)現(xiàn)辦理手機(jī)套餐功能詳解
這篇文章主要介紹了Java使用建造者模式實(shí)現(xiàn)辦理手機(jī)套餐功能,較為詳細(xì)的描述了建造者模式的概念、原理并結(jié)合實(shí)例形式分析了Java使用建造者模式實(shí)現(xiàn)的辦理手機(jī)套餐功能具體步驟與相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2018-05-05Web三大組件之Filter,Listener和Servlet詳解
這篇文章主要為大家詳細(xì)介紹了Web三大組件之Filter,Listener和Servlet,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-03-03solr 配置中文分析器/定義業(yè)務(wù)域/配置DataImport功能方法(測(cè)試用)
下面小編就為大家?guī)硪黄猻olr 配置中文分析器/定義業(yè)務(wù)域/配置DataImport功能方法(測(cè)試用)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09基于Spring中的線程池和定時(shí)任務(wù)功能解析
下面小編就為大家?guī)硪黄赟pring中的線程池和定時(shí)任務(wù)功能解析。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09SpringBoot使用@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)的并行執(zhí)行
在SpringBoot中,如果使用@Scheduled注解來定義多個(gè)定時(shí)任務(wù),默認(rèn)情況下這些任務(wù)將會(huì)被安排在一個(gè)單線程的調(diào)度器中執(zhí)行,這意味著,這些任務(wù)將會(huì)串行執(zhí)行,而不是并行執(zhí)行,本文介紹了SpringBoot使用@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)的并行執(zhí)行,需要的朋友可以參考下2024-06-06