14 Spring Cloud vs Dubbo Conflict or Strong Integration

14 Spring Cloud vs Dubbo- Conflict or Strong Integration- #

When it comes to choosing between Dubbo and Spring Cloud for microservice development, many developers have compared these two projects. In this chapter, we will take a closer look at these two projects and see if they compete or collaborate.

Introduction to Project Development #

Let’s start by looking at the development history of Dubbo:

  1. Dubbo was open-sourced by Alibaba in 2012 and quickly adopted by many internet companies.
  2. Due to a change in company strategy, the project stopped maintenance in October 2014, and the version remained stagnant at dubbo-2.4.11. During this non-maintenance period, Dangdang, based on a branch, re-open sourced the DubboX framework.
  3. In September 2017, Alibaba announced the reboot of the Dubbo project and released a new version dubbo-2.5.4. It would be promoted as a long-term open-source product by the community, and subsequent versions started to be developed again.
  4. In February 2018, Alibaba donated Dubbo to the Apache Software Foundation for incubation.
  5. In May 2019, Apache Dubbo officially became a top-level project.

Dubbo is positioned as a high-performance and lightweight open-source Java RPC framework, and its ecosystem has become increasingly prosperous with the growing community.

img

To help developers quickly get started with Dubbo applications, an official website was launched that allows for the rapid generation of Dubbo projects based on Spring Boot, similar to start.spring.io. More detailed documentation can be found on the official website.

Spring Cloud has a relatively short history. Spring Cloud originated from Spring, so let’s review the development of Spring:

  1. It can be traced back to 2002 when Rod Johnson wrote a book called “Expert One-on-One J2EE Design and Development.”
  2. Around February 2003, Rod, Juergen, and Yann started collaborating on a development project, and Yann came up with the name “Spring” for the new framework. Yann Caroff left the team early on, and Rod Johnson left in 2012, while Juergen Hoeller remained an active member of the Spring development team.
  3. In November 2007, under Rod’s leadership, the Interface21 project was renamed to SpringSource.
  4. In 2007, SpringSource obtained Series A financing of $10 million from Benchmark Capital. During this period, SpringSource also acquired several companies, such as Hyperic and G2One.
  5. In August 2009, VMWare acquired SpringSource for $420 million.
  6. In July 2012, Rod Johnson left the team.
  7. In April 2013, VMware, EMC, and GE created a joint venture named Pivotal. All Spring-related projects were transferred to Pivotal.
  8. In 2014, Pivotal released Spring Boot.
  9. In 2015, Dell acquired EMC.
  10. In 2015, Pivotal released Spring Cloud.
  11. In 2018, Pivotal Corporation went public in New York.

From the long development history, we can see that Spring has also experienced ups and downs. In fact, it is hard to avoid using Spring for Java development since the Spring community has had a great influence on the development of Java. Spring Cloud, based on the Spring and Spring Boot ecosystems, provides a whole set of out-of-the-box solutions for microservice development, making it very convenient for developers to get started quickly. Behind it, commercial companies provide strong support, and many core project components can be seen to embody Netflix OSS, such as Eureka, which has been well validated in Netflix’s distributed production environment, thereby enhancing its credibility.

Dubbo has a significant market influence in China, but Spring Cloud has a larger market share internationally. After all, the advantage of a native English environment and the support of the Spring community contribute to the flourishing ecosystem. With Dubbo officially becoming an Apache top-level project, its adoption in the international market is expected to increase.

Technical Selection Dilemma #

The intersection between the two can be found around 2015. On the one hand, Dubbo was widely used in China and was known for its simplicity, ease of use, and high performance. However, its community was nearly stagnant. At the same time, Spring Cloud emerged with a new approach, rapidly spreading in lightweight Java development based on the principle of “convention over configuration” in Spring Boot. However, it is also an undeniable fact that Spring Cloud has more component types, less documentation, and a steeper learning curve.

In the early days, when making technology choices, it was common to compare the two. A typical example is the article “Choosing a Foundational Framework for Microservice Architecture: Spring Cloud or Dubbo?” In 2016, when our company was making technology choices, I faced the same problem. Considering the business requirements at that time and the technical capabilities of the team, we eventually chose Dubbo, which was in a non-maintenance period, and planned to consider refactoring when the requirements couldn’t be met.

In the early days, Spring Cloud’s service registration center was based on Eureka, while Dubbo used ZooKeeper as its registry. Having two separate service management solutions for a set of services led to high complexity. Integrating these two frameworks was not easy since they operated in their own domains with their own solutions.

In recent years, the emergence of Spring Cloud Alibaba has greatly improved this two-way selection dilemma. On the one hand, it can replace some of the no longer maintained project functions in the original project. On the other hand, it can integrate Alibaba’s technology ecosystem with the Spring Cloud ecosystem. Both can use Nacos as a service registration center and also replace Spring Cloud Config, providing a more concise and intuitive configuration management solution that reduces complexity. In addition, a RPC solution called Dubbo has also been introduced into the Spring Cloud ecosystem, complementing the RESTful approach.

Practical Integration of the Two #

Now let’s integrate two projects through a business feature - members redeeming car wash vouchers with points to get their cars washed.

New parent project - parking-carwash #

This module needs to provide an RPC interface for external use. The code structure is as follows:

img

There are two sub-modules under this parent project. The “api” project is a simple Java project that is built into a jar file for external project dependencies and calls. The “serv” project is a Spring Boot application that provides actual business services and runs independently in the form of a jar file.

parking-carwash-serv service provider #

In the “api” module, write the interfaces and place the corresponding entities here so that they can be used normally when being relied upon. Configure the basic components according to the previous approach, and then introduce the related Dubbo jars. The configuration is as follows:

<!-- Must include the spring-boot-starter-actuator package, otherwise there will be an error during startup. -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-actuator</artifactId>
</dependency>

<!-- Dubbo Spring Cloud Starter -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>

To experience the application of the yaml configuration file, the bootstrap.yml file is introduced in this project, but you can also use an application configuration file:

spring:
  application:
    name: carwash-service
  main:
    allow-bean-definition-overriding: true
  cloud:
    nacos:
      discovery:
        enabled: true
        register-enabled: true
        server-addr: 127.0.0.1:8848

Configure Dubbo in application.properties:

# dubbo config
dubbo.protocols.dubbo.name=dubbo
dubbo.protocols.dubbo.port=-1
dubbo.scan.base-packages=com.mall.parking.carwash.serv.service
dubbo.registry.address=spring-cloud://127.0.0.1
dubbo.registry.register=true
dubbo.application.qos.enable=false

# This configuration item is used to prevent a large amount of naming logs output from Nacos
logging.level.com.alibaba.nacos.client.naming=error

Writing an interface and implementation class:

public interface WashService {
    int wash(String json) throws BusinessException;
}

@Service(protocol = "dubbo")
@Slf4j
public class WashServiceImpl implements WashService {

    @Autowired
    CarWashMapper carWashMapper;

    @Override
    public int wash(String json) throws BusinessException {
        CarWash carWash = JSONObject.parseObject(json, CarWash.class);
        int rtn = carWashMapper.insertSelective(carWash);
        log.info("car wash data = " + json + "> write suc...");

        return rtn;
    }

}

Note: The @Service annotation is no longer used with Spring, but instead uses the annotation org.apache.dubbo.config.annotation.Service provided by Dubbo. The comment in the code provides multiple attribute values for configuring various features of the interface, such as service grouping, service version, whether service registration is delayed, service retry times, etc., depending on the actual usage.

The Application startup class is the same as a normal Spring Cloud startup class. After startup, the service of this module can be seen registered successfully in the Nacos service list.

parking-member service consumer #

Add Dubbo’s JAR and API interface JAR to the previously constructed parking-member project.

<!-- Dubbo Spring Cloud Starter -->
<dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<dependency>
        <groupId>com.mall.parking.root</groupId>
        <artifactId>parking-carwash-api</artifactId>
        <version>0.0.1-SNAPSHOT</version>
</dependency>

Configuration in application.properties:

#dubbo config
dubbo.registry.address=nacos://localhost:8848
dubbo.application.qos.enable=false
dubbo.cloud.subscribed-services=carwash-service
spring.main.allow-bean-definition-overriding=true
#don't check if the service provider is online, it's recommended to enable this in production environment
dubbo.consumer.check=false

#more naming logs output,config this to avoid more log output
logging.level.com.alibaba.nacos.client.naming=error

Writing the service invocation class:

@Reference
WashService washService; // Call the service like calling a local JAR

/**
* {"plateNo":"湘 AG7890","ticketCode":"Ts0999"}
* 
* @param json
* @return
* @throws BusinessException
*/
@PostMapping("/wash")
public CommonResult<Integer> wash(String json) throws BusinessException {
    log.debug("add vehicle = " + json);
    CommonResult<Integer> result = new CommonResult<>();

    int rtn = washService.wash(json);
    result.setRespData(rtn);
    return result;
}

Testing #

After the service provider is started, start the member module service. Use Postman to access the vehicle/wash method and you will see that the service is called successfully and the data is written to the park-carwash database.

With this, we have successfully integrated Dubbo and Spring Cloud projects into one project, benefiting from both the high performance of the RPC framework and the convenience of the full ecosystem.

Here’s a question for you to ponder:

  • There are two ways to import Dubbo’s starter: spring-cloud-starter-dubbo and dubbo-spring-boot-starter. What is the difference between these two methods?