SpringCloud輕松集成Dubbo實現RPC調用
很久之前在做微服務架構選型的時候就聽說阿里的微服務RPC框架dubbo锐峭,當時與Spring Cloud以http協議調用的架構做對比际邻。發(fā)現dubbo的rpc框架學習成本較高绊起,代碼入侵性強,本身生態(tài)不完整蝴簇,需要整合多個外部組件杯活,故選擇了相對性能弱一點的Spring Cloud全家桶。
直到Spring Cloud Alibaba的出現熬词,使用Nacos作為服務發(fā)現與注冊旁钧,同時兼容使用Feign的http方式和使用Dubbo的rpc方式調用。
Spring Cloud 為什么需要RPC
在Spring Cloud構建的微服務系統中互拾,大多數的開發(fā)者使用都是官方提供的Feign組件來進行內部服務通信均践,這種聲明式的HTTP客戶端使用起來非常的簡潔、方便摩幔、優(yōu)雅,并且和開發(fā)平臺鞭铆、語言無關或衡,但是通常情況下,HTTP并不會開啟KeepAlive功能车遂,即當前連接為短連接封断,短連接的缺點是每次請求都需要建立TCP連接,這使得其效率變得相當低下舶担。
對外部提供REST API服務是一件非常好的事情坡疼,但是如果內部調用也是使用HTTP調用方式,就會顯得顯得性能低下衣陶,Spring Cloud默認使用的Feign組件進行內部服務調用就是使用的HTTP協議進行調用柄瑰,這時,我們如果內部服務使用RPC調用剪况,對外使用REST API教沾,將會是一個非常不錯的選擇。
引用至:Dubbo 與 Spring Cloud 完美結合
使用Dubbo Spring Cloud使用內部的RPC協議調用幾乎是零成本的改造译断。
一授翻、系統結構
- cloud-gateway 作為cloud集群的網關孙咪,外部的路由轉發(fā)使用http協議堪唐,內部的服務調用使用dubbo協議
- cloud-user和cloud-mq之間的遠程調用使用dubbo協議
- 使用Nacos作為服務注冊與發(fā)現和配置中心的服務
- 使用Sentinel作為服務器http和dubbo調用的流量控制服務
目錄結構
├── cloud-admin # 服務監(jiān)控├── cloud-gateway # 服務網關├── cloud-mq # mq服務├── cloud-provider # 服務接口└── cloud-user # user服務
二、服務接口提供方實現
1. 服務接口定義
public interface UserProvider { UserDTO checkUser(String userName, String password); UserDTO findByUserName(String userName);}@Data@Builder@NoArgsConstructor@AllArgsConstructorpublic class UserDTO implements Serializable { String userName; String realName; String password;}
- 服務接口是服務提供方和消費方的契約翎蹈,包含服務的方法傳輸對象DTO淮菠。由于涉及多個應用服務的引入,最好是將其獨立成Module
- DTO對象必須實現Serializable接口
2. 引入dubbo包
POM
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId></dependency>
spring-boot-starter-actuator 也是必須的
3. 服務接口實現
import org.apache.dubbo.config.annotation.Service;@Servicepublic class UserProviderImpl implements UserProvider { @Autowired private UserService userService; @Override public UserDTO checkUser(String userName, String password) { User user = userService.checkUser(userName, password); return UserConvertor.toDTO(user); }}
@Service必須是org.apache.dubbo.config.annotation.Service
4. 配置Dubbo服務相關的信息
spring: main: allow-bean-definition-overriding: true dubbo: scan: base-packages: fun.barryhome.cloud.provider #指定 Dubbo 服務實現類的掃描基準包 protocols: dubbo: name: dubbo # Dubbo 的協議名稱 port: -1 # port 為協議端口( -1 表示自增端口荤堪,從 20880 開始) registry: address: spring-cloud://localhost # 掛載到 Spring Cloud 注冊中心
啟動后有可能出現連接失敗兜材,不影響使用
java.net.ConnectException: Connection refused (Connection refused) at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.8.0_111] at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_111] at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_111]
三理澎、服務調用方實現
1. 引入依賴包
<!--服務接口--><dependency> <groupId>fun.barryhome</groupId> <artifactId>cloud-provider</artifactId> <version>0.0.1-SNAPSHOT</version> <scope>compile</scope></dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId></dependency>
2. 調用服務接口
import org.apache.dubbo.config.annotation.Reference;public class UserController { @Reference private UserProvider userProvider; @GetMapping(value = "/sessionUser") public UserDTO sessionUser(HttpServletRequest request) { String userName = request.getHeader("X-User-Name"); if (Strings.isEmpty(userName)) { throw new RuntimeException("沒有找到用戶"); } return userProvider.findByUserName(userName); }}
3. 配置Dubbo服務相關的信息
dubbo: cloud: subscribed-services: cloud-user # 服務提供方的服務名 consumer: check: false loadbalance: "leastactive" # 最小活躍數負載均衡 registry: # 掛載到 Spring Cloud 注冊中心 address: spring-cloud://localhost
dubbo.consumer.check:用于啟動時是否檢查服務提供方是否運行正常,如果不正常將不能啟動調用方
dubbo.consumer.loadbalance:負載均衡策略
- RandomLoadBalance:隨機曙寡,按權重設置隨機概率
- ConsistentHashLoadBalance:一致性哈希算法
- LeastActiveLoadBalance:最小活躍數負載均衡
- RoundRobinLoadBalance:根據權重進輪訓
四糠爬、總結
- 服務間使用了長連接,在正常運行時举庶,提供方某個節(jié)點斷掉后會需要一段時間來切換执隧,可使用sentinel來控制快速切換可用節(jié)點
- 使用dubbo進行遠程調用,內部調用性能上有所提供户侥,調用方式上也相對簡單
- 與sentinel配合镀琉,合理使用負載策略,可實現更多功能蕊唐,如灰度發(fā)布屋摔,版本控制等
- 性能的提升讓調用鏈增加成為可能性,可實現更小粒度的微服務拆分與組合
五替梨、源代碼
https://gitee.com/hypier/barry-cloud
來源;掘金