在
面試中,很容易被面試官問到:
如何設計一個RPC框架?
你可能沒被問到過,可能是運氣好,也可能是你還沒到這個等級。通常月薪20k以上,基本上都會問一些設計性的題目。
站在面試官角度:問這類題目,總比一個八股文強,這裡面會牽涉到很多技術點。例如:設計模式、通訊協定、動態代理、虛擬化、執行緒池等知識。
好吧,不扯遠了,我們開始聊今天的話題。
RPC全程為Remote procedure call 遠端過程調用,這幾個字很多人可能並不是特別的理解,再簡單的說就是:
像調用本地方法一樣呼叫遠端服務。
例如,下面一個案例:一個使用者操作服務:
public interface UserService{ String findUserNameById(Integer userId); } @Service public class UserServiceImpl implements UserService{ String findUserNameById(Integer userId){ //查数据或查缓存获取到用户名 return "田哥" } }
現在一個controller裡想呼叫UserServiceImpl的findUserNameById方法取得使用者名稱。
@RestController public class UserController{ @Resource private UserService userService; @GetMapping("/test") public String test(){ return userService.findUserNameById(1); } }
假設UserController、UserServiceImpl、UserService三個類別都在同一個專案裡,controller想呼叫findUserNameById方法是非常簡單的。
但是,如果controller是另一個項目,也想像上面那樣調用(細微的不同,感覺還是一樣),這時候我們就可以用到了RPC框架。
1、需要把介面UserService放在一個單獨專案裡,我們通常稱之為api專案。
2、需要把UserServiceImpl放在一個單獨專案裡,我們通常稱之為叫做provider專案。
3、controller嘛,透過是web之類的(consumer)專案裡
4、把api打成jar包,然後consumer專案、provider專案都引用它。
市面上的RPC框架,比如說:Dubbo (阿里)、Thrift(FaceBook)、gRpc(Google)、brpc (百度)等都在不同重點去解決最初的目的,有的想極致完美,有的追求極致性能,有的偏向極致簡單。
回到前面我們說的像是呼叫本地一樣的呼叫遠端服務,到底需要哪些技術支撐呢?
UserService
定義,沒有實作類,想要呼叫一個介面的方法?那就只能搞個代理對象了。 為什麼需要註冊中心,我之前分享過:
#根据上面的这些原理,田哥也搞了一个RPC框架,命名为mink(一个动物的名称)。
--mink ----mink-rpc rpc基本功能 ----mink-registry 服务注册与发现 ----mink-spring 集成SpringBoot
然后,我们把mink-spring打成jar包,服务发布和服务引用都把这个jar给依赖进去。
上面,我们创造了轮子,下面,我们就来看如何使用。
mink-demo就是一个Spring Boot项目,有三个module。
我们把mink-api
打成jar包,共consumer和provider使用。
也就是我们在consumer和provider都引入:
<dependency> <groupId>com.tian</groupId> <artifactId>mink-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
下面,我们来看看provider端的代码:
<dependency> <groupId>com.tian</groupId> <artifactId>mink-spring</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.tian</groupId> <artifactId>mink-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.5.4</version> </dependency>
我们的mink框架,只需要引入mink-spring依赖即可。
接着就是properties的配置:
mink.rpc.servicePort=20880 mink.rpc.registryType=0 mink.rpc.registryAddress=127.0.0.1:2181
再来看看具体服务实现类:
package com.tian.service; import com.tian.annotation.MinkService; /** * @author tianwc 公众号:java后端技术全栈、面试专栏 * @version 1.0.0 * @description 用户服务 * @createTime 2022年08月23日 18:16 */ @MinkService public class UserServiceImpl implements UserService { @Override public String findUserNameByiD(Integer id) { System.out.println("服务调用"); return "tian"; } }
这一步,我们只需要在实现类上加上注解@MinkService
即可。
最后就是项目启动类:
@ComponentScan(basePackages = {"com.tian.service","com.tian"}) @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
我们启动项目(注册中心用的是zookeeper):
从日志中可以看出,我们的服务已经成功注册到注册中心了。
下面,我们来看看consumer端代码。
首先来看看依赖:
<dependency> <groupId>com.tian</groupId> <artifactId>mink-spring</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.tian</groupId> <artifactId>mink-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.5.4</version> </dependency>org.springframework.boot spring-boot-starter-web 2.5.4
这依赖也很简单,没什么好说的。
再来看看properties配置项:
mink.rpc.registryType=0 mink.rpc.registryAddress=127.0.0.1:2181 server.port=8090
是不是也很简单?
再来看看我们的controller代码:
package com.tian.controller; import com.tian.annotation.MinkReference; import com.tian.service.UserService; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author tianwc 公众号:java后端技术全栈、面试专栏 * @version 1.0.0 * @description 消费端 * @createTime 2022年08月23日 23:08 */ @RestController public class UserController { @MinkReference private UserService userService; @RequestMapping("/test") public String test() { return userService.findUserNameByiD(1); } }
需要用到对应服务,只需要添加注解@MinkReference
即可。
最后就是项目启动类,简单的不行。
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
启动日志:
访问:http://localhost:8090/test
成功!整个过程,非常轻松地集成mink框架并在业务代码中使用。
总结起来,其实就三步:
1、pom中添加依赖
2、properties文件中配置注册中心信息
3、使用的时候加上注解@MinkReference
或 @MinkService即可
以上是手寫RPC框架,真不是為了裝13!的詳細內容。更多資訊請關注PHP中文網其他相關文章!