一 前言 幾大RPC框架介紹 1.支持多語言的RPC框架,google的gRPC,Apache(facebook)的Thrift 2.只支持特定語言的RPC框架,例如新浪的Motan 3.支持服務治理等服務化特性的分散式框架,例如阿裡的dubbo 4.擁有完整生態的spring cloud spri ...
一 前言
幾大RPC框架介紹
spring cloud遠程調用方式---Feign
Feign是一個聲明似的web服務客戶端,它使得編寫web服務客戶端變得更加容易。使用Fegin創建一個介面並對它進行註解。它具有可插拔的註解支持包括Feign註解與JAX-RS註解,Feign還支持可插拔的編碼器與解碼器,Spring Cloud 增加了對 Spring MVC的註解,Spring Web 預設使用了HttpMessageConverters, Spring Cloud 集成 Ribbon 和 Eureka 提供的負載均衡的HTTP客戶端 Feign。
官方解釋: Feign is a Java to HTTP client binder inspired by Retrofit, JAXRS-2.0, and WebSocket. Feign's first goal was reducing the complexity of binding Denominator uniformly to HTTP APIs regardless of ReSTfulness.
Feign的兩種調用方式
1 直接在調用者聲明Feign客戶端
如下圖所示, service-b 聲明一個介面, 去調用路徑為 /user/get 的服務 service-a 的服務
2 在被調用者介面Api中聲明Feign客戶端
如下圖, 在被調用者中聲明介面, 去調用自己, 這種方法遵循面向介面編程, 而且使用起來, 就類似dubbo一樣, @Autowire直接註入就可以使用了.
以上可能看得讀者一頭霧水, 以下具體的代碼流程, 可以方便更加具體的瞭解
二 案例1直接在調用者聲明Feign客戶端代碼實現
以下步驟為手把手教學, 請明白我的良苦用心
步驟0 創建一個SpringCloud-Eureka註冊中心
首先創建一個父項目
把其他都刪除, 剩下pom文件
以下為父項目的依賴
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.fegin</groupId> <artifactId>test</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>pom</packaging> <!--springboot version 2.1.4--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR1</spring-cloud.version> </properties> <!--springcloud version Greenwish.SR1--> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
創建eureka項目
項目結構如圖
添加eureka的依賴
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>test</artifactId> <groupId>com.fegin</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>eureka</artifactId> <!--eureka服務端配置--> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> </project>
添加application.yml
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
# 是否把自己作為服務註冊到其他服務註冊中心
registerWithEureka: false
# 是否從其他的服務中心同步服務列表
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
# 關閉保護機制,預設true
enable-self-preservation: false
# 剔除失效服務間隔,預設60000
eviction-interval-timer-in-ms: 3000
添加啟動類代碼EurekaApplication
/** * @author c-can-z */ @EnableEurekaServer @SpringBootApplication public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class,args); } }
瀏覽器輸入 http://localhost:8761/
步驟1 準備一個服務servicea --- 該服務為被調用者


步驟2 準備一個服務serviceb --- 該服務為調用者
創建一個serviceb
添加一下serviceb必須的依賴
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>test</artifactId> <groupId>com.fegin</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>serviceb</artifactId> <dependencies> <!--springboot web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--springboot 測試--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--eureka客戶端配置--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <!--微服務調用--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--zipkin客戶端配置, 已經包含sleuth--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency> </dependencies> </project>
把 application.properties 修改為 application.yml, 本服務名稱為 service-b 埠為 9992
server:
port: 9992
spring:
application:
name: service-b
zipkin:
base-url: http://localhost:9411
sleuth:
sampler:
probability: 1
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
registry-fetch-interval-seconds: 5 #eureka client刷新本地緩存時間,預設30
instance:
prefer-ip-address: true
#Eureka客戶端向服務端發送心跳的時間間隔,單位為秒(客戶端告訴服務端自己會按照該規則),預設30
lease-renewal-interval-in-seconds: 5
#Eureka服務端在收到最後一次心跳之後等待的時間上限,單位為秒,超過則剔除(客戶端告訴服務端按照此規則等待自己),預設90
lease-expiration-duration-in-seconds: 7
feign:
client:
config:
default:
connectTimeout: 7000
readTimeout: 7000
service-b:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
logging:
level:
root: info
導入啟動類文件
@SpringBootApplication @EnableFeignClients public class SeriveBApplication { public static void main(String[] args) { SpringApplication.run(SeriveBApplication.class,args); } }
創建Feign客戶端
//在創建該步驟的時候, 需要關註一下步驟1的說明 //@FeignClient(name = "service-a")註解來綁定該介面對應servic-a服務 @FeignClient(name = "service-a") public interface UserFeginClient { //service-a服務對應資源路徑.必須加上@RequestParam, 否則會報錯,返回參數也必須對應上 @RequestMapping("user/get") String get(@RequestParam("id")Long id); }
在controller中直接進行調用
@RestController @RequestMapping("/product") public class ProductController { @Autowired private UserFeginClient userFeginClient; @RequestMapping("/get") public String get(Long id){ return "產品服務抽獎: "+userFeginClient.get(id); } }
步驟3 測試Feign調用效果

三 案例2 在被調用者介面Api中聲明Feign客戶端代碼實現
步驟1 創建servicecapi, 該Api用來創建Feign客戶端

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>test</artifactId> <groupId>com.fegin</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>servicec-api</artifactId> <dependencies> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--微服務調用--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> </dependencies> </project>
實體類product
public class Product implements Serializable { private Long id; private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }
}
feign客戶端
/** * 服務名稱 * @author c-can-z */ @FeignClient(name="service-c") public interface ProductFeignApi { //動態代理需要的地址, 但是我們實際操作不到 @RequestMapping("/servicec/get") Product get(@RequestParam("id") Long id); }
步驟2 創建servicec服務
項目結構
service項目依賴
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>test</artifactId> <groupId>com.fegin</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>servicec</artifactId> <dependencies> <!--springboot web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--eureka客戶端配置--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--zipkin客戶端配置, 已經包含sleuth--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency> <!--springboot 測試--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--導入api--> <dependency> <groupId>com.fegin</groupId> <artifactId>servicec-api</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> </project>
servicec的 application.yml
server:
port: 9993
spring:
application:
name: service-c
zipkin:
base-url: http://localhost:9411
sleuth:
sampler:
probability: 1
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
registry-fetch-interval-seconds: 5 #eureka client刷新本地緩存時間,預設30
instance:
prefer-ip-address: true
#Eureka客戶端向服務端發送心跳的時間間隔,單位為秒(客戶端告訴服務端自己會按照該規則),預設30
lease-renewal-interval-in-seconds: 5
#Eureka服務端在收到最後一次心跳之後等待的時間上限,單位為秒,超過則剔除(客戶端告訴服務端按照此規則等待自己),預設90
lease-expiration-duration-in-seconds: 7
feign:
client:
config:
default:
connectTimeout: 7000
readTimeout: 7000
logging:
level:
root: info
實現Feign客戶端介面, 也是該文章的核心代碼
採用實現的方式
/** * 遠程調用介面的實現類 * @author c-can-z */ @RestController public class ProductFeignClient implements ProductFeignApi { @Override public Product get(Long id) { Product product = new Product(); product.setId(id); product.setName("我是服務C"); return product; } }
servicec的啟動類
@SpringBootApplication public class ProductServerApplication { public static void main(String[] args) { SpringApplication.run(ProductServerApplication.class, args); } }
步驟3 創建serviced服務去調用servicec
項目結構
註意啟動類的位置, servicecapi的路徑必須被啟動類掃描到
serviced的依賴,
註意, 必須引入servicec的api, 有人會說有代碼侵入的問題, 但是對比案例1, 如果多個項目調用, 要創建多個Feign客戶端, 孰是孰非, 還得看項目的具體需求
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>test</artifactId> <groupId>com.fegin</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>serviced</artifactId> <dependencies> <!--springboot web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--springboot 測試--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--eureka客戶端配置--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--微服務調用--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--zipkin客戶端配置, 已經包含sleuth--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency> <dependency> <groupId>com.fegin</groupId> <artifactId>servicec-api</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> </project>
serviced的 application.yml
server:
port: 9994
spring:
application:
name: service-d
zipkin:
base-url: http://localhost:9411
sleuth:
sampler:
probability: 1
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
registry-fetch-interval-seconds: 5 #eureka client刷新本地緩存時間,預設30
instance:
prefer-ip-address: true
#Eureka客戶端向服務端發送心跳的時間間隔,單位為秒(客戶端告訴服務端自己會按照該規則),預設30
lease-renewal-interval-in-seconds: 5
#Eureka服務端在收到最後一次心跳之後等待的時間上限,單位為秒,超過則剔除(客戶端告訴服務端按照此規則等待自己),預設90
lease-expiration-duration-in-seconds: 7
feign:
client:
config:
default:
connectTimeout: 7000
readTimeout: 7000
logging:
level:
root: info
serviced的控制類
/** * @author c-can-z */ @RestController @RequestMapping("/order") public class OrderController { @Autowired private ProductFeignApi productFeignApi; @RequestMapping("/get") public String get(Long id){ Product product = productFeignApi.get(id); return "訂單為: 貨品:" + product.getName() + ", 貨品id:"+product.getId(); } }
serviced的啟動類
/** * @author c-can-z */ @SpringBootApplication @EnableFeignClients public class ServiceDApplication { public static void main(String[] args) { SpringApplication.run(ServiceDApplication.class,args); } }
步驟4 測試Feign調用效果
http://localhost:9994/order/get?id=5
四 總結
到了這裡, 不知道你是否理解 直接在調用者聲明Feign客戶端 或者 在被調用者介面Api中聲明Feign客戶端
直接在調用者聲明Feign客戶端:
每一個服務調用其他服務, 就需要創建一個客戶端, 從代碼方面來說, 相對比較麻煩
在被調用者介面Api中聲明Feign客戶端:
從調用者來看, 使用起來就跟使用淘寶的dubbo一樣方便, 但是每一個服務調用其他服務,

-
該問題可能導致tomcat啟動成功了,但是瀏覽器輸入http://127.0.0.1:8080無法顯示tomcat的歡迎界面 打開Tomcat安裝目錄下的bin文件下的setclasspath.sh,在文檔開頭添加如下語句: export JAVA_HOME=你的jdk路徑 export JRE_H ...
-
Linux 命令之 scp 命令詳解 一、scp 簡介 scp 命令用於不同主機之間複製文件和目錄。 scp 是 secure copy 的縮寫,是 基於 ssh 協議進行安全的遠程文件拷貝命令。 scp 想要免密進行複製,需要發送秘鑰給相應的節點。 scp 是加密的,rcp 是不加密的,scp 是 ...
-
KubeSphere 不僅支持部署在 Linux 之上,還支持在已有 Kubernetes 集群之上部署 KubeSphere,自動納管 Kubernetes 集群的已有資源與容器。 前提條件 版本: Helm = 2.10.0`(不支持 helm 2.16.0 " 6894" ),且已安裝了 Ti ...
-
CentOS 7 下安裝部署java+tomcat+mysql 前置:CentOS7安裝:https://jingyan.baidu.com/article/b7001fe1d1d8380e7382dd72.html 附常用命令合集:https://www.cnblogs.com/icebutter ...
-
今天,下午刷手機的時候,突然看到kali出了一個非常新穎的主題;該主題可以使得kali系統偽裝成windows 10而變得低調起來;就像下麵這樣: 具體新聞鏈接:https://www.freebuf.com/news/221582.html Kali Undercover模式 如果你在某些環境中想 ...
-
最近需要使用 kali 源安裝一些軟體: 配置 sources.list,根據如下鏈接:http://mirrors.ustc.edu.cn/help/kali.html 獲取 公鑰;apt-key adv --keyserver keyserver.ubuntu.com --recv ED444F ...
-
前言 上周四,伺服器突然掛了。SSH都連接不上,日常的小程式後臺直接down掉,小程式每日大概3K左右訪問量。於是乎就開啟了,排查之後。 排查階段 什麼先別說,先把服務恢復再說。重啟阿裡雲伺服器,SSH連接。開啟nginx,redis,mysql,java服務。一系列操作,先把服務先啟動了。 伺服器 ...
-
一 Kubernetes DNS介紹1.1 Kubernetes DNS發展作為服務發現機制的基本功能,在集群內需要能夠通過服務名對服務進行訪問,因此需要一個集群範圍內的DNS服務來完成從服務名到ClusterIP的解析。DNS服務在Kubernetes的發展過程中經歷了3個階段,SkyDNS --... ...
-
前言 ASP.NET Core 後我們的配置變得更加輕量級了,在ASP.NET Core中,配置模型得到了顯著的擴展和增強,應用程式配置可以存儲在多環境變數配置中,appsettings.json用戶機密等 並可以通過應用程式中的相同界面輕鬆訪問,除此之外,ASP.NET中的新配置系統允許使用Opt ...
-
1. 需求 在應用退出時(點擊右上角的關閉按鈕)彈出一個確認按鈕可以說是一個最常見的操作了,例如記事本的“你是否保存”: 但這個功能在UWP上居然有點小複雜。這篇文章將解釋如何實現這個功能。 2. CloseRequested 為了監視應用退出事件,我本來使用了 "CoreApplication.E ...
-
Aspose.PDF for .NET是一種高級PDF處理和解析API,用於在跨平臺應用程式中執行文檔管理和操作任務。API可以輕鬆用於生成,修改,轉換,渲染,保護和列印PDF文檔,而無需使用Adobe Acrobat。此外,還提供PDF壓縮選項,表格創建和操作,圖形和圖像功能,廣泛的超鏈接功能,印 ...
-
Netnr.Login 第三方OAuth授權登錄 支持第三方登錄 三方參考文檔 參考文檔 參考文檔 參考文檔 參考文檔 參考文檔 參考文檔 參考文檔 參考文檔 參考文檔 參考文檔 參考文檔 安裝 (NuGet) 修改配置信息(密鑰、回調等) 提醒:一般所有第三方登錄都有一個 state 參數,用於防 ...
-
場景 效果 註: 博客主頁: https://blog.csdn.net/badao_liumang_qizhi 關註公眾號 霸道的程式猿 獲取編程相關電子書、教程推送與免費下載。 實現 新建一個Form窗體,設計頁面佈局如下 摺疊效果的向上和向下按鈕是PictureBox,從上往下依次的Tag標簽 ...
-
netnrf 響應式框架 用於快速開發的響應式框架 演示: v3.x 前端採用 jQuery + Bootstrap + EasyUI + AceAdmin + fontAwesome 後端採用 .NET Core + EF + SQL(SQLServer、MySQL、PostgreSQL、SQLi ...
-
Aspose.Words for .Net是一種高級Word文檔處理API,用於執行各種文檔管理和操作任務。API支持生成,修改,轉換,呈現和列印文檔,而無需在跨平臺應用程式中直接使用Microsoft Word。 Aspose.Words API提供了將Microsoft Word文檔從DOC或D ...
-
DefaultValue,顧名思義,預設值的意思。但這個預設值不是用來顯示的,它的作用是當屬性設置的值(無法代碼寫還是屬性視窗輸入)與DefaultValue相同時,會區別顯示,比如其它值加粗,DefaultValue不加粗。 DefaultValue可以勉強理解為密碼或者暗號,雖然看不到,但值對了 ...
-
var grpBalance = listBalance.GroupBy(m => new { m.MerChantId, m.Name}).Distinct().Select(t => new balInfo { MerChantId = t.Key.MerChantId, Name = t.Ke ...
-
EF提供了三種方式來實現項目,分別是: (1)代碼優先方法: (2)模型優先方法: (3)資料庫優先方法: 本篇主要記錄在Vs2010環境下使用代碼優先的方式實現資料庫和後端代碼數據交互,語言為C#,資料庫為sqlserver 2008。 1.在sqlserver中創建資料庫 "StudentDB" ...