在微服務項目中,如果我們想實現服務間調用,一般會選擇Feign。之前介紹過一款HTTP客戶端工具Retrofit,配合SpringBoot非常好用!其實Retrofit不僅支持普通的HTTP調用,還能支持微服務間的調用,負載均衡和熔斷限流都能實現。今天我們來介紹下Retrofit在Spring Cloud Alibaba下的使用,希望對大家有所幫助!
搭建
在使用之前我們需要先搭建Nacos和Sentinel,再準備一個被調用的服務,使用之前的nacos-user-service即可。
java?-jar?sentinel-dashboard-1.6.3.jar
/***?Created?by?macro?on?2019/8/29.*/
@RestController
@RequestMapping("/user")
public?class?UserController?{private?Logger?LOGGER?=?LoggerFactory.getLogger(this.getClass());@Autowiredprivate?UserService?userService;@PostMapping("/create")public?CommonResult?create(@RequestBody?User?user)?{userService.create(user);return?new?CommonResult("操作成功",?200);}@GetMapping("/{id}")public?CommonResult<User>?getUser(@PathVariable?Long?id)?{User?user?=?userService.getUser(id);LOGGER.info("根據id獲取用戶信息,用戶名稱為:{}",user.getUsername());return?new?CommonResult<>(user);}@GetMapping("/getUserByIds")public?CommonResult<List<User>>?getUserByIds(@RequestParam?List<Long>?ids)?{List<User>?userList=?userService.getUserByIds(ids);LOGGER.info("根據ids獲取用戶信息,用戶列表為:{}",userList);return?new?CommonResult<>(userList);}@GetMapping("/getByUsername")public?CommonResult<User>?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的基本使用,包括服務間調用、服務限流和熔斷降級。
集成與配置
<dependencies><!--Nacos注冊中心依賴--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--Sentinel依賴--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency><!--Retrofit依賴--><dependency><groupId>com.github.lianjiatech</groupId><artifactId>retrofit-spring-boot-starter</artifactId><version>2.2.18</version></dependency></dependencies>
server:port:?8402
spring:application:name:?nacos-retrofit-servicecloud: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#?熔斷降級實現方式degrade-type:?sentinel#?熔斷資源名稱解析器resource-name-parser:?com.github.lianjiatech.retrofit.spring.boot.degrade.DefaultResourceNameParser
/***?Retrofit相關配置*?Created?by?macro?on?2022/1/26.*/
@Configuration
public?class?RetrofitConfig?{@Bean@Autowiredpublic?ServiceInstanceChooser?serviceInstanceChooser(LoadBalancerClient?loadBalancerClient)?{return?new?SpringCloudServiceInstanceChooser(loadBalancerClient);}
}
服務間調用
/***?定義Http接口,用于調用遠程的User服務*?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<User>?getUser(@Path("id")?Long?id);@GET("/user/getByUsername")CommonResult<User>?getByUsername(@Query("username")?String?username);@POST("/user/update")CommonResult?update(@Body?User?user);@POST("/user/delete/{id}")CommonResult?delete(@Path("id")?Long?id);
}
服務限流
/***?限流功能*?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);}}
熔斷降級
/***?熔斷降級*?Created?by?macro?on?2019/11/7.*/
@Api(tags?=?"CircleBreakerController",description?=?"熔斷降級")
@RestController
@RequestMapping("/breaker")
public?class?CircleBreakerController?{private?Logger?LOGGER?=?LoggerFactory.getLogger(CircleBreakerController.class);@Autowiredprivate?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,"服務降級返回",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,"服務降級返回",200);}
}
總結
Retrofit給了我們除Feign和Dubbo之外的第三種微服務間調用選擇,使用起來還是非常方便的。記得之前在使用Feign的過程中,實現方的Controller經常要抽出一個接口來,方便調用方來實現調用,接口實現方和調用方的耦合度很高。如果當時使用的是Retrofit的話,這種情況會大大改善。總的來說,Retrofit給我們提供了更加優雅的HTTP調用方式,不僅是在單體應用中,在微服務應用中也一樣!
參考資料
官方文檔:https://github.com/LianjiaTech/retrofit-spring-boot-starter
項目源碼地址
https://github.com/macrozheng/springcloud-learning
往期推薦
Spring Cloud OpenFeign奪命連環9問,這誰受得了?
2022-02-18
玩轉Nacos參數配置!多圖勿點
2022-02-21
【萬字長文】Spring Cloud Alibaba ?開箱即用!
2022-02-16
求點贊、在看、分享三連
總結
以上是生活随笔為你收集整理的再见 Feign!推荐一款微服务间调用神器,跟 SpringCloud 绝配!的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。