Using Retrofit with Spring Cloud Alibaba for Seamless Microservice Calls
This guide demonstrates how to integrate Retrofit into a Spring Cloud Alibaba environment, covering Nacos registration, Sentinel fault‑tolerance, service discovery, load balancing, and detailed code examples for building, configuring, and testing microservice communication, rate limiting, and circuit‑breaker features.
In microservice projects, Retrofit can be used instead of Feign for HTTP calls, supporting ordinary HTTP requests, inter‑service calls, load balancing, and circuit breaking. This article shows how to use Retrofit under Spring Cloud Alibaba.
Prerequisite Knowledge
This article assumes familiarity with Nacos and Sentinel. Refer to earlier articles if needed.
Setup
First, install Nacos and Sentinel, then prepare a service named nacos-user-service for registration.
Download
nacos-server-1.3.0.zipfrom the official Nacos releases page.
Unzip the package and run
startup.cmdin the
bindirectory. Access the console at
http://localhost:8848/nacoswith username and password both set to
nacos.
Download
sentinel-dashboard-1.6.3.jarfrom the Sentinel releases page and start it with:
<code>java -jar sentinel-dashboard-1.6.3.jar</code>Sentinel runs on port
8080; login with username and password
sentinel.
Start the
nacos-user-servicewhich provides CRUD APIs for a
Userentity; it will register itself with Nacos.
Integration and Configuration
Add the following dependencies to pom.xml :
<code><dependencies>
<!-- Nacos discovery -->
<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></code>Configure Nacos, Sentinel, and Retrofit in application.yml :
<code>server:
port: 8402
spring:
application:
name: nacos-retrofit-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8080
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
</code>Add a Java configuration class to provide a ServiceInstanceChooser bean:
<code>@Configuration
public class RetrofitConfig {
@Bean
@Autowired
public ServiceInstanceChooser serviceInstanceChooser(LoadBalancerClient loadBalancerClient) {
return new SpringCloudServiceInstanceChooser(loadBalancerClient);
}
}
</code>Service-to-Service Calls
Define a Retrofit client interface using @RetrofitClient and specify the target service ID:
<code>@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);
}
</code>Run two instances of nacos-user-service and one instance of nacos-retrofit-service . Nacos will register all services, and Swagger can be used to test the APIs at http://localhost:8402/swagger-ui/ . Logs show that Retrofit automatically performs load balancing based on the serviceId annotation.
Rate Limiting
Rate limiting is delegated to Sentinel. Create a controller to test the limits:
<code>@Api(tags = "RateLimitController", description = "Rate limiting demo")
@RestController
@RequestMapping("/rateLimit")
public class RateLimitController {
@ApiOperation("Limit by resource name")
@GetMapping("/byResource")
@SentinelResource(value = "byResource", blockHandler = "handleException")
public CommonResult byResource() {
return new CommonResult("Rate limited by resource", 200);
}
@ApiOperation("Limit by URL")
@GetMapping("/byUrl")
@SentinelResource(value = "byUrl", blockHandler = "handleException")
public CommonResult byUrl() {
return new CommonResult("Rate limited by URL", 200);
}
@ApiOperation("Custom block handler")
@GetMapping("/customBlockHandler")
@SentinelResource(value = "customBlockHandler", blockHandler = "handleException", blockHandlerClass = CustomBlockHandler.class)
public CommonResult blockHandler() {
return new CommonResult("Custom block handling", 200);
}
public CommonResult handleException(BlockException exception) {
return new CommonResult(exception.getClass().getCanonicalName(), 200);
}
}
</code>Define a rule in the Sentinel dashboard based on the resource name; rapid requests will trigger the limit and return the block response.
Circuit Breaking
Circuit breaking also relies on Sentinel. Create a controller with fallback methods:
<code>@Api(tags = "CircleBreakerController", description = "Circuit breaking demo")
@RestController
@RequestMapping("/breaker")
public class CircleBreakerController {
@Autowired
private UserService userService;
@ApiOperation("Simple fallback")
@RequestMapping(value = "/fallback/{id}", method = RequestMethod.GET)
@SentinelResource(value = "fallback", fallback = "handleFallback")
public CommonResult fallback(@PathVariable Long id) {
return userService.getUser(id);
}
@ApiOperation("Fallback with ignored exception")
@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, "Service degraded", 200);
}
public CommonResult handleFallback2(Long id, Throwable e) {
User defaultUser = new User(-2L, "defaultUser2", "123456");
return new CommonResult<>(defaultUser, "Service degraded", 200);
}
}
</code>If the target nacos-user-service does not contain a user with the requested ID, an exception is thrown and the fallback method returns a default user object.
Conclusion
Retrofit offers a third option for inter‑service communication besides Feign and Dubbo. It simplifies the coupling between provider and consumer by allowing interface‑based HTTP calls, and works well in both monolithic and microservice architectures.
References
Official documentation: https://github.com/LianjiaTech/retrofit-spring-boot-starter
Project source code: https://github.com/macrozheng/springcloud-learning
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.