<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          再見 Feign!推薦一款微服務(wù)間調(diào)用神器,跟 SpringCloud 絕配!

          共 8019字,需瀏覽 17分鐘

           ·

          2022-02-28 07:53

          在微服務(wù)項目中,如果我們想實現(xiàn)服務(wù)間調(diào)用,一般會選擇Feign。之前介紹過一款HTTP客戶端工具Retrofit,配合SpringBoot非常好用!其實Retrofit不僅支持普通的HTTP調(diào)用,還能支持微服務(wù)間的調(diào)用,負載均衡和熔斷限流都能實現(xiàn)。今天我們來介紹下Retrofit在Spring Cloud Alibaba下的使用,希望對大家有所幫助!

          搭建

          在使用之前我們需要先搭建Nacos和Sentinel,再準備一個被調(diào)用的服務(wù),使用之前的nacos-user-service即可。

          • 首先從官網(wǎng)下載Nacos,這里下載的是nacos-server-1.3.0.zip文件,下載地址:https://github.com/alibaba/nacos/releases
          • 解壓安裝包到指定目錄,直接運行bin目錄下的startup.cmd,運行成功后訪問Nacos,賬號密碼均為nacos,訪問地址:http://localhost:8848/nacos
          • 接下來從官網(wǎng)下載Sentinel,這里下載的是sentinel-dashboard-1.6.3.jar文件,下載地址:https://github.com/alibaba/Sentinel/releases
          • 下載完成后輸入如下命令運行Sentinel控制臺;
          java?-jar?sentinel-dashboard-1.6.3.jar
          • Sentinel控制臺默認運行在8080端口上,登錄賬號密碼均為sentinel,通過如下地址可以進行訪問:http://localhost:8080
          • 接下來啟動nacos-user-service服務(wù),該服務(wù)中包含了對User對象的CRUD操作接口,啟動成功后它將會在Nacos中注冊。
          /**
          ?*?Created?by?macro?on?2019/8/29.
          ?*/

          @RestController
          @RequestMapping("/user")
          public?class?UserController?{

          ????private?Logger?LOGGER?=?LoggerFactory.getLogger(this.getClass());

          ????@Autowired
          ????private?UserService?userService;

          ????@PostMapping("/create")
          ????public?CommonResult?create(@RequestBody?User?user)?{
          ????????userService.create(user);
          ????????return?new?CommonResult("操作成功",?200);
          ????}

          ????@GetMapping("/{id}")
          ????public?CommonResult?getUser(@PathVariable?Long?id)?{
          ????????User?user?=?userService.getUser(id);
          ????????LOGGER.info("根據(jù)id獲取用戶信息,用戶名稱為:{}",user.getUsername());
          ????????return?new?CommonResult<>(user);
          ????}

          ????@GetMapping("/getUserByIds")
          ????public?CommonResult>?getUserByIds(@RequestParam?List?ids)?{
          ????????List?userList=?userService.getUserByIds(ids);
          ????????LOGGER.info("根據(jù)ids獲取用戶信息,用戶列表為:{}",userList);
          ????????return?new?CommonResult<>(userList);
          ????}

          ????@GetMapping("/getByUsername")
          ????public?CommonResult?getByUsername(@RequestParam?String?username)?{
          ????????User?user?=?userService.getByUsername(username);
          ????????return?new?CommonResult<>(user);
          ????}

          ????@PostMapping("/update")
          ????public?CommonResult?update(@RequestBody?User?user)?{
          ????????userService.update(user);
          ????????return?new?CommonResult("操作成功",?200);
          ????}

          ????@PostMapping("/delete/{id}")
          ????public?CommonResult?delete(@PathVariable?Long?id)?{
          ????????userService.delete(id);
          ????????return?new?CommonResult("操作成功",?200);
          ????}
          }

          使用

          接下來我們來介紹下Retrofit的基本使用,包括服務(wù)間調(diào)用、服務(wù)限流和熔斷降級。

          集成與配置

          • 首先在pom.xml中添加Nacos、Sentinel和Retrofit相關(guān)依賴;
          <dependencies>
          ????
          ?????<dependency>
          ?????????<groupId>com.alibaba.cloudgroupId>
          ?????????<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
          ?????dependency>
          ????
          ?????<dependency>
          ?????????<groupId>com.alibaba.cloudgroupId>
          ?????????<artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
          ?????dependency>
          ?????
          ?????<dependency>
          ?????????<groupId>com.github.lianjiatechgroupId>
          ?????????<artifactId>retrofit-spring-boot-starterartifactId>
          ?????????<version>2.2.18version>
          ?????dependency>
          ?dependencies>
          • 然后在application.yml中對Nacos、Sentinel和Retrofit進行配置,Retrofit配置下日志和開啟熔斷降級即可;
          server:
          ??port:?8402
          spring:
          ??application:
          ????name:?nacos-retrofit-service
          ??cloud:
          ????nacos:
          ??????discovery:
          ????????server-addr:?localhost:8848?#配置Nacos地址
          ????sentinel:
          ??????transport:
          ????????dashboard:?localhost:8080?#配置sentinel?dashboard地址
          ????????port:?8719
          retrofit:
          ??log:
          ????#?啟用日志打印
          ????enable:?true
          ????#?日志打印攔截器
          ????logging-interceptor:?com.github.lianjiatech.retrofit.spring.boot.interceptor.DefaultLoggingInterceptor
          ????#?全局日志打印級別
          ????global-log-level:?info
          ????#?全局日志打印策略
          ????global-log-strategy:?body
          ??#?熔斷降級配置
          ??degrade:
          ????#?是否啟用熔斷降級
          ????enable:?true
          ????#?熔斷降級實現(xiàn)方式
          ????degrade-type:?sentinel
          ????#?熔斷資源名稱解析器
          ????resource-name-parser:?com.github.lianjiatech.retrofit.spring.boot.degrade.DefaultResourceNameParser
          • 再添加一個Retrofit的Java配置,配置好選擇服務(wù)實例的Bean即可。
          /**
          ?*?Retrofit相關(guān)配置
          ?*?Created?by?macro?on?2022/1/26.
          ?*/

          @Configuration
          public?class?RetrofitConfig?{

          ????@Bean
          ????@Autowired
          ????public?ServiceInstanceChooser?serviceInstanceChooser(LoadBalancerClient?loadBalancerClient)?{
          ????????return?new?SpringCloudServiceInstanceChooser(loadBalancerClient);
          ????}
          }

          服務(wù)間調(diào)用

          • 使用Retrofit實現(xiàn)微服務(wù)間調(diào)用非常簡單,直接使用@RetrofitClient注解,通過設(shè)置serviceId為需要調(diào)用服務(wù)的ID即可;
          /**
          ?*?定義Http接口,用于調(diào)用遠程的User服務(wù)
          ?*?Created?by?macro?on?2019/9/5.
          ?*/

          @RetrofitClient(serviceId?=?"nacos-user-service",?fallback?=?UserFallbackService.class)
          public?interface?UserService?
          {
          ????@POST("/user/create")
          ????CommonResult?create(@Body?User?user);

          ????@GET("/user/{id}")
          ????CommonResult?getUser(@Path("id")?Long?id);

          ????@GET("/user/getByUsername")
          ????CommonResult?getByUsername(@Query("username")?String?username);

          ????@POST("/user/update")
          ????CommonResult?update(@Body?User?user);

          ????@POST("/user/delete/{id}")
          ????CommonResult?delete(@Path("id")?Long?id);
          }
          • 我們可以啟動2個nacos-user-service服務(wù)和1個nacos-retrofit-service服務(wù),此時Nacos注冊中心顯示如下;
          • 然后通過Swagger進行測試,調(diào)用下獲取用戶詳情的接口,發(fā)現(xiàn)可以成功返回遠程數(shù)據(jù),訪問地址:http://localhost:8402/swagger-ui/
          • 查看nacos-retrofit-service服務(wù)打印的日志,兩個實例的請求調(diào)用交替打印,我們可以發(fā)現(xiàn)Retrofit通過配置serviceId即可實現(xiàn)微服務(wù)間調(diào)用和負載均衡。

          服務(wù)限流

          • Retrofit的限流功能基本依賴Sentinel,和直接使用Sentinel并無區(qū)別,我們創(chuàng)建一個測試類RateLimitController來試下它的限流功能;
          /**
          ?*?限流功能
          ?*?Created?by?macro?on?2019/11/7.
          ?*/

          @Api(tags?=?"RateLimitController",description?=?"限流功能")
          @RestController
          @RequestMapping("/rateLimit")
          public?class?RateLimitController?{

          ????@ApiOperation("按資源名稱限流,需要指定限流處理邏輯")
          ????@GetMapping("/byResource")
          ????@SentinelResource(value?=?"byResource",blockHandler?=?"handleException")
          ????public?CommonResult?byResource()?{
          ????????return?new?CommonResult("按資源名稱限流",?200);
          ????}

          ????@ApiOperation("按URL限流,有默認的限流處理邏輯")
          ????@GetMapping("/byUrl")
          ????@SentinelResource(value?=?"byUrl",blockHandler?=?"handleException")
          ????public?CommonResult?byUrl()?{
          ????????return?new?CommonResult("按url限流",?200);
          ????}

          ????@ApiOperation("自定義通用的限流處理邏輯")
          ????@GetMapping("/customBlockHandler")
          ????@SentinelResource(value?=?"customBlockHandler",?blockHandler?=?"handleException",blockHandlerClass?=?CustomBlockHandler.class)
          ????public?CommonResult?blockHandler()?
          {
          ????????return?new?CommonResult("限流成功",?200);
          ????}

          ????public?CommonResult?handleException(BlockException?exception){
          ????????return?new?CommonResult(exception.getClass().getCanonicalName(),200);
          ????}

          }
          • 接下來在Sentinel控制臺創(chuàng)建一個根據(jù)資源名稱進行限流的規(guī)則;
          • 之后我們以較快速度訪問該接口時,就會觸發(fā)限流,返回如下信息。

          熔斷降級

          • Retrofit的熔斷降級功能也基本依賴于Sentinel,我們創(chuàng)建一個測試類CircleBreakerController來試下它的熔斷降級功能;
          /**
          ?*?熔斷降級
          ?*?Created?by?macro?on?2019/11/7.
          ?*/

          @Api(tags?=?"CircleBreakerController",description?=?"熔斷降級")
          @RestController
          @RequestMapping("/breaker")
          public?class?CircleBreakerController?{

          ????private?Logger?LOGGER?=?LoggerFactory.getLogger(CircleBreakerController.class);
          ????@Autowired
          ????private?UserService?userService;

          ????@ApiOperation("熔斷降級")
          ????@RequestMapping(value?=?"/fallback/{id}",method?=?RequestMethod.GET)
          ????@SentinelResource(value?=?"fallback",fallback?=?"handleFallback")
          ????public?CommonResult?fallback(@PathVariable?Long?id)?{
          ????????return?userService.getUser(id);
          ????}

          ????@ApiOperation("忽略異常進行熔斷降級")
          ????@RequestMapping(value?=?"/fallbackException/{id}",method?=?RequestMethod.GET)
          ????@SentinelResource(value?=?"fallbackException",fallback?=?"handleFallback2",?exceptionsToIgnore?=?{NullPointerException.class})
          ????public?CommonResult?fallbackException(@PathVariable?Long?id)?
          {
          ????????if?(id?==?1)?{
          ????????????throw?new?IndexOutOfBoundsException();
          ????????}?else?if?(id?==?2)?{
          ????????????throw?new?NullPointerException();
          ????????}
          ????????return?userService.getUser(id);
          ????}

          ????public?CommonResult?handleFallback(Long?id)?{
          ????????User?defaultUser?=?new?User(-1L,?"defaultUser",?"123456");
          ????????return?new?CommonResult<>(defaultUser,"服務(wù)降級返回",200);
          ????}

          ????public?CommonResult?handleFallback2(@PathVariable?Long?id,?Throwable?e)?{
          ????????LOGGER.error("handleFallback2?id:{},throwable?class:{}",?id,?e.getClass());
          ????????User?defaultUser?=?new?User(-2L,?"defaultUser2",?"123456");
          ????????return?new?CommonResult<>(defaultUser,"服務(wù)降級返回",200);
          ????}
          }
          • 由于我們并沒有在nacos-user-service中定義id為4的用戶,調(diào)用過程中會產(chǎn)生異常,所以訪問如下接口會返回服務(wù)降級結(jié)果,返回我們默認的用戶信息。

          總結(jié)

          Retrofit給了我們除Feign和Dubbo之外的第三種微服務(wù)間調(diào)用選擇,使用起來還是非常方便的。記得之前在使用Feign的過程中,實現(xiàn)方的Controller經(jīng)常要抽出一個接口來,方便調(diào)用方來實現(xiàn)調(diào)用,接口實現(xiàn)方和調(diào)用方的耦合度很高。如果當時使用的是Retrofit的話,這種情況會大大改善??偟膩碚f,Retrofit給我們提供了更加優(yōu)雅的HTTP調(diào)用方式,不僅是在單體應(yīng)用中,在微服務(wù)應(yīng)用中也一樣!

          參考資料

          官方文檔:https://github.com/LianjiaTech/retrofit-spring-boot-starter

          項目源碼地址

          https://github.com/macrozheng/springcloud-learning


          往期推薦

          Spring Cloud OpenFeign奪命連環(huán)9問,這誰受得了?

          2022-02-18

          玩轉(zhuǎn)Nacos參數(shù)配置!多圖勿點

          2022-02-21

          【萬字長文】Spring Cloud Alibaba ?開箱即用!

          2022-02-16




          求點贊、在看、分享三連
          瀏覽 49
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久免费视屏 | 国产卡一卡二高清无码在线 | 久久机热这里只有精品 | 天天撸AV| 婷婷五月天丁香 |