SpringCloud輕鬆集成Dubbo實現RPC調用

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"很久之前在做微服務架構選型的時候就聽說阿里的微服務RPC框架"},{"type":"codeinline","content":[{"type":"text","text":"dubbo"}]},{"type":"text","text":",當時與"},{"type":"codeinline","content":[{"type":"text","text":"Spring Cloud"}]},{"type":"text","text":"以http協議調用的架構做對比。發現"},{"type":"codeinline","content":[{"type":"text","text":"dubbo"}]},{"type":"text","text":"的rpc框架學習成本較高,代碼入侵性強,本身生態不完整,需要整合多個外部組件,故選擇了相對性能弱一點的"},{"type":"codeinline","content":[{"type":"text","text":"Spring Cloud"}]},{"type":"text","text":"全家桶。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"直到Spring Cloud Alibaba的出現,使用"},{"type":"codeinline","content":[{"type":"text","text":"Nacos"}]},{"type":"text","text":"作爲服務發現與註冊,同時兼容使用"},{"type":"codeinline","content":[{"type":"text","text":"Feign"}]},{"type":"text","text":"的"},{"type":"codeinline","content":[{"type":"text","text":"http"}]},{"type":"text","text":"方式和使用"},{"type":"codeinline","content":[{"type":"text","text":"Dubbo"}]},{"type":"text","text":"的"},{"type":"codeinline","content":[{"type":"text","text":"rpc"}]},{"type":"text","text":"方式調用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"Spring Cloud 爲什麼需要RPC"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":">在Spring Cloud構建的微服務系統中,大多數的開發者使用都是官方提供的Feign組件來進行內部服務通信,這種聲明式的HTTP客戶端使用起來非常的簡潔、方便、優雅,並且和開發平臺、語言無關,但是通常情況下,HTTP並不會開啓KeepAlive功能,即當前連接爲短連接,短連接的缺點是每次請求都需要建立TCP連接,這使得其效率變的相當低下。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":">對外部提供REST API服務是一件非常好的事情,但是如果內部調用也是使用HTTP調用方式,就會顯得顯得性能低下,Spring Cloud默認使用的Feign組件進行內部服務調用就是使用的HTTP協議進行調用,這時,我們如果內部服務使用RPC調用,對外使用REST API,將會是一個非常不錯的選擇。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"*引用至:"},{"type":"link","attrs":{"href":"https://www.cnblogs.com/babycomeon/p/11546737.html","title":""},"content":[{"type":"text","text":"Dubbo 與 Spring Cloud 完美結合"}]},{"type":"text","text":"*"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用Dubbo Spring Cloud使用內部的RPC協議調用幾乎是零成本的改造。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"一、系統結構"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/8a/8a623cf14046a2f1d84ffccb1c0c21bb.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"cloud-gateway"}]},{"type":"text","text":" 作爲cloud集羣的網關,外部的路由轉發使用"},{"type":"text","marks":[{"type":"strong"}],"text":"http"},{"type":"text","text":"協議,內部的服務調用使用"},{"type":"text","marks":[{"type":"strong"}],"text":"dubbo"},{"type":"text","text":"協議"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"cloud-user"}]},{"type":"text","text":"和"},{"type":"codeinline","content":[{"type":"text","text":"cloud-mq"}]},{"type":"text","text":"之間的遠程調用使用"},{"type":"text","marks":[{"type":"strong"}],"text":"dubbo"},{"type":"text","text":"協議"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用"},{"type":"codeinline","content":[{"type":"text","text":"Nacos"}]},{"type":"text","text":"作爲"},{"type":"text","marks":[{"type":"strong"}],"text":"服務註冊與發現"},{"type":"text","text":"和*"},{"type":"text","marks":[{"type":"italic"}],"text":"配置中心"},{"type":"text","text":"*的服務"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用"},{"type":"codeinline","content":[{"type":"text","text":"Sentinel"}]},{"type":"text","text":"作爲服務間"},{"type":"text","marks":[{"type":"strong"}],"text":"http"},{"type":"text","text":"和*"},{"type":"text","marks":[{"type":"italic"}],"text":"dubbo"},{"type":"text","text":"*調用的流量控制服務"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"目錄結構"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":""},"content":[{"type":"text","text":"├── cloud-admin # 服務監控\n├── cloud-gateway # 服務網關\n├── cloud-mq # mq服務\n├── cloud-provider # 服務接口\n└── cloud-user # user服務"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"二、服務接口提供方實現"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1. 服務接口定義"}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public interface UserProvider {\n UserDTO checkUser(String userName, String password);\n UserDTO findByUserName(String userName);\n}\n\n@Data\n@Builder\n@NoArgsConstructor\n@AllArgsConstructor\npublic class UserDTO implements Serializable {\n String userName;\n String realName;\n String password;\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"服務接口是服務提供方和消費方的契約,包含服務的方法傳輸對象DTO。由於涉及多個應用服務的引入,最好是將其獨立成"},{"type":"text","marks":[{"type":"strong"}],"text":"Module"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"DTO對象必須實現"},{"type":"codeinline","content":[{"type":"text","text":"Serializable"}]},{"type":"text","text":"接口"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2. 引入`dubbo`包"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"POM"}]},{"type":"codeblock","attrs":{"lang":"xml"},"content":[{"type":"text","text":" \n com.alibaba.cloud\n spring-cloud-starter-dubbo\n\n\n org.springframework.boot\n spring-boot-starter-actuator\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"spring-boot-starter-actuator"}]},{"type":"text","text":" 也是必須的"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3. 服務接口實現"}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"import org.apache.dubbo.config.annotation.Service;\n\n@Service\npublic class UserProviderImpl implements UserProvider {\n\n @Autowired\n private UserService userService;\n\n @Override\n public UserDTO checkUser(String userName, String password) {\n\n User user = userService.checkUser(userName, password);\n return UserConvertor.toDTO(user);\n }\n\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"@Service"}]},{"type":"text","text":"必須是"},{"type":"text","marks":[{"type":"strong"}],"text":"org.apache.dubbo.config.annotation.Service"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4. 配置Dubbo服務相關的信息"}]},{"type":"codeblock","attrs":{"lang":"yml"},"content":[{"type":"text","text":"spring:\n main:\n allow-bean-definition-overriding: true\n \ndubbo:\n scan:\n base-packages: fun.barryhome.cloud.provider #指定 Dubbo 服務實現類的掃描基準包\n protocols:\n dubbo:\n name: dubbo # Dubbo 的協議名稱\n port: -1 # port 爲協議端口( -1 表示自增端口,從 20880 開始)\n\n registry:\n address: spring-cloud://localhost # 掛載到 Spring Cloud 註冊中心"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"啓動後有可能出現連接失敗,不影響使用"}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"java.net.ConnectException: Connection refused (Connection refused)\n\tat java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.8.0_111]\n\tat java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_111]\n\tat java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_111]\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"三、服務調用方實現"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1. 引入依賴包"}]},{"type":"codeblock","attrs":{"lang":"xml"},"content":[{"type":"text","text":"\n\n fun.barryhome\n cloud-provider\n 0.0.1-SNAPSHOT\n compile\n\n \n com.alibaba.cloud\n spring-cloud-starter-dubbo\n\n\n org.springframework.boot\n spring-boot-starter-actuator\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2. 調用服務接口"}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"import org.apache.dubbo.config.annotation.Reference;\n\npublic class UserController {\n\n @Reference\n private UserProvider userProvider;\n\n @GetMapping(value = \"/sessionUser\")\n public UserDTO sessionUser(HttpServletRequest request) {\n\n String userName = request.getHeader(\"X-User-Name\");\n if (Strings.isEmpty(userName)) {\n throw new RuntimeException(\"沒有找到用戶\");\n }\n\n return userProvider.findByUserName(userName);\n }\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3. 配置Dubbo服務相關的信息"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"yml"},"content":[{"type":"text","text":"dubbo:\n cloud:\n subscribed-services: cloud-user # 服務提供方的服務名\n consumer:\n check: false\n loadbalance: \"leastactive\" # 最小活躍數負載均衡\n\n registry:\n # 掛載到 Spring Cloud 註冊中心\n address: spring-cloud://localhost"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"dubbo.consumer.check"}]},{"type":"text","text":":用於啓動時是否檢查服務提供方是否運行正常,如果不正常將不能啓動調用方"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"dubbo.consumer.loadbalance"}]},{"type":"text","text":":負載均衡策略"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"RandomLoadBalance:隨機,按權重設置隨機概率"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"ConsistentHashLoadBalance:一致性哈希算法"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"LeastActiveLoadBalance:最小活躍數負載均衡"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"RoundRobinLoadBalance:根據權重進輪訓"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"四、總結"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"服務間使用了長連接,在正常運行時,提供方某個節點斷掉後會需要一段時間來切換,可使用"},{"type":"codeinline","content":[{"type":"text","text":"sentinel"}]},{"type":"text","text":"來控制快速切換可用節點"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"使用dubbo進行遠程調用,內部調用性能上有所提供,調用方式上也相對簡單"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"與"},{"type":"codeinline","content":[{"type":"text","text":"sentinel"}]},{"type":"text","text":"配合,合理使用負載策略,可實現更多功能,如灰度發佈,版本控制等"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"性能的提升讓調用鏈增加成爲可能性,可實現更小粒度的微服務拆分與組合"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"五、源代碼"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://gitee.com/hypier/barry-cloud","title":""},"content":[{"type":"text","text":"https://gitee.com/hypier/barry-cloud"}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"六、請關注我的公衆號"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/62/629ab9a8e71fdadbe20e9f7c365b04bf.jpeg","alt":null,"title":"請關注我的公衆號","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章