Article directory
-
- 1. Dubbo’s past and present
- 2. Quick start of Dubbo
-
- 2.1. The basic structure of Dubbo
- 2.2、Nacos
- 2.3. Management background
- 2.4. Getting Started Case
-
- 2.4.1. Service Providers
-
- build environment
- Code
- configuration file
- 2.4.2. Service consumers
-
- build environment
- Code
- configuration file
- 2.5. Code optimization
- 3. Advanced features of Dubbo
-
- 3.2, timeout and retry
- 3.3. Startup check
- 3.4, multiple versions
- 3.5. Load balancing
- 4. Spring Cloud integrates Dubbo
-
- 4.1. Function overview
- 4.2. Getting Started Case
-
- 4.2.1. Extraction interface
- 4.2.2. Project dependencies
- 4.2.3. Service provider
- 4.2.4. Service consumers
1. Dubbo’s past and present life
On October 27, 2011, Alibaba open-sourced Dubbo, the core framework of its SOA service-based governance solution, and the design concepts of service governance and SOA began to be gradually implemented in the domestic software industry and widely used.
-
The early version of dubbo follows the idea of SOA and is an important component of service-oriented architecture.
-
The current version of Dubbo is used as Spring Cloud’s binary communication solution to take advantage of Dubbo’s performance
2. Quick start of Dubbo
2.1, the basic structure of Dubbo
Node role description:
node | role description |
---|---|
Provider | The service provider of the exposed service. |
Consumer | The service consumer who calls the remote service. |
Registry | Registry for service registration and discovery. |
Monitor | A monitoring center that counts service calls and call times. |
Call relationship description:
- The service container is responsible for starting, loading, and running the service provider.
- When the service provider starts, it registers the services it provides with the registration center.
- When a service consumer starts, it subscribes to the registration center for the services it needs.
- The registration center returns the service provider address list to the consumer. If there is a change, the registration center will push the change data to the consumer based on the long connection.
- Service consumers, from the provider address list, select a provider to call based on the soft load balancing algorithm, and if the call fails, select another provider to call.
- Service consumers and providers accumulate the number of calls and call time in memory, and regularly send statistical data to the monitoring center every minute.
2.2, Nacos
Nacos is a product of Alibaba. It is a platform integrating service discovery and configuration management. It is very popular in China.
1. Find the nacos installation package in today’s information
2. Unzip to a directory without Chinese and special characters
3. Enter the bin directory and execute the startup command
#Enter the bin directory cd bin #start up startup.cmd -m standalone
4. Browser viewing: http://127.0.0.1:8848/nacos
2.3, management background
DubboAdmin is a management console provided by Alibaba Management, which can implement functions such as service query, detailed display, and service testing. DubboAdmin can better help developers manage and monitor services
#1. Download code: git clone https://github.com/apache/dubbo-admin.git #2. Specify the registration center address in dubbo-admin-server/src/main/resources/application.properties #3. Build mvn clean package -D maven.test.skip=true #4. Start mvn --projects dubbo-admin-server spring-boot:run #or cd dubbo-admin-distribution/target; java -jar dubbo-admin-0.1.jar #5. Visit http://localhost:8080
2.4, entry case
Requirements: Use Dubbo to build a distributed architecture and complete user query based on user id
2.4.1, service provider
Building the environment
(1) Create user-provider module import dependencies
<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <!--Dubbo's starting dependency--> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.8</version> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-registry-nacos</artifactId> <version>2.7.8</version> </dependency> </dependencies>
(2) Write the boot class
package cn.itcast.user; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @MapperScan("cn.itcast.user.mapper") @SpringBootApplication public class UserProviderApplication {<!-- --> public static void main(String[] args) {<!-- --> SpringApplication.run(UserProviderApplication.class, args); } }
Code Implementation
(1) UserServiceImpl
package cn.itcast.user.service; import cn.itcast.user.api.UserService; import cn.itcast.user.domain.User; import cn.itcast.user.mapper.UserMapper; import org.apache.dubbo.config.annotation.DubboService; import org.springframework.beans.factory.annotation.Autowired; @DubboService public class UserServiceImpl implements UserService {<!-- --> @Autowired private UserMapper userMapper; //Query user name by id public String queryUsername(Long id) {<!-- --> return userMapper.findById(id).getUsername(); } }
Configuration file
server: port: 18081 spring: datasource: url: jdbc:mysql://localhost:3306/dubbo-demo?useSSL=false username: root password: root driver-class-name: com.mysql.jdbc.Driver application: name: user-provider record: level: cn.itcast: debug pattern: dateformat: HH:mm:ss:SSS dubbo: protocol: name: dubbo port: 20881 registry: address: nacos://127.0.0.1:8848 scan: base-packages: cn.itcast.user.service
2.4.2, service consumers
Building the environment
(1) Create user-consumer module import dependencies
<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--Dubbo's starting dependency--> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.8</version> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-registry-nacos</artifactId> <version>2.7.8</version> </dependency> </dependencies>
(2) Configure the boot class
package cn.itcast.user; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class UserConsumerApplication {<!-- --> public static void main(String[] args) {<!-- --> SpringApplication.run(UserConsumerApplication.class, args); } }
Code Implementation
package cn.itcast.user.controller; import cn.itcast.user.api.UserService; import cn.itcast.user.domain.User; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @Slf4j @RestController @RequestMapping("/user") public class UserController {<!-- --> // reference remote service @DubboReference private UserService userService; @GetMapping("/username/1") public String findUserName(@PathVariable("id") Long id) {<!-- --> return userService. queryUsername(id); } }
Configuration file
server: port: 18080 spring: application: name: user-consumer record: level: cn.itcast: debug pattern: dateformat: HH:mm:ss:SSS dubbo: registry: address: nacos://127.0.0.1:8848
2.5, code optimization
Extract the interface as an independent module, and put all the domains related to the interface into this module
(1) Create a user-api module to introduce dependencies
(2) Import the UserService interface and User object into the user-api module
(3) The User object implements the serialization interface
package cn.itcast.user.domain; import lombok.Data; import java.io.Serializable; @Data public class User implements Serializable {<!-- --> private Long id; private String username; private String address; }
3, Dubbo advanced features
3.2, timeout and retry
The service consumer is blocked and waiting when calling the service provider. At this time, the service consumer will wait forever.
At a certain peak moment, a large number of requests are requesting service consumers at the same time, which will cause a large accumulation of threads, which will inevitably cause an avalanche.
- Dubbo uses the timeout mechanism to solve this problem (use the timeout attribute to configure the timeout period, the default value is 1000, in milliseconds)
- If the timeout period is short, the request will fail when the network fluctuates. Dubbo avoids such problems through the retry mechanism
Add configuration information to the user-consumer module
dubbo: registry: address: nacos://127.0.0.1:8848 consumer: timeout: 3000 retries: 0
3.3, start check
In order to ensure the normal availability of the service, Dubbo will check whether the dependent service is available by default at startup, and will throw an exception if it is not available
This is a very necessary configuration in a formal environment to ensure the smooth operation of the entire calling link
During development, there are often situations where there is no provider. May cause problems with development tests due to startup checks
Can be closed by check=false
Add configuration information to the user-consumer module
dubbo: registry: address: nacos://127.0.0.1:8848 consumer: check: false
3.4, multiple versions
Grayscale release: When a new function appears, some users will be allowed to use the new function first, and all users will be migrated to the new function when there is no problem with user feedback.
Dubbo provides support for multiple versions of the provider, and smoothly handles project function upgrade deployment
(1) user-provider defines a new service implementation class UserServiceImpl2, specifying the version
@DubboService(version = "2.0.0") public class UserServiceImpl2 implements UserService {<!-- --> ………… }
(2) When the user-consumer consumer calls, the specified version is called
@RestController @RequestMapping("/user") public class UserController {<!-- --> // reference remote service @DubboReference(version = "2.0.0") private UserService userService; ……… }
3.5, load balancing
During cluster deployment, Dubbo provides 4 load balancing strategies to help consumers find the optimal provider and call
-
Random : random by weight, the default value. Set random probability by weight.
-
RoundRobin : round robin by weight
-
LeastActive: The least number of active calls, random with the same number of active calls.
-
ConsistentHash: Consistent Hash, requests with the same parameters are always sent to the same provider.
@RestController @RequestMapping("/user") public class UserController {<!-- --> // reference remote service @DubboReference(loadbalance = "roundrobin") private UserService userService; }
4. SpringCloud integrates Dubbo
Generally speaking, the RPC protocol has better performance than REST. Many developers hope to enjoy the ecology of Spring Cloud while taking into account the efficiency of PRC. SpringCloud Alibaba solves this problem very well.
4.1, function overview
Integrating Dubbo into Spring Cloud is mainly to replace Ribbo or Feign for remote calls. After joining Dubbo, the overall structure is as follows:
4.2, entry case
4.2.1, extraction interface
Define the interface module dubbo-api, and extract the UserService interface to this module
package cn.itcast.dubbo.api; import cn.itcast.dubbo.domain.User; public interface UserService {<!-- --> User queryById(Long id); }
4.2.2, project dependencies
Add SpringCloud Alibaba dependency to the parent project
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.5.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency>
Consumers and providers introduce nacos registry and Dubbo dependencies
<!--dependence of nacos registration center--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--springcloud alibaba dubbo dependency --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId> </dependency> <dependency> <groupId>cn.itcast</groupId> <artifactId>dubbo-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
4.2.3, service provider
Modify UserService to implement the UserApi interface. And use @DubboService annotation to replace @Service to expose dubbo service externally
package cn.itcast.user.service; import cn.itcast.dubbo.api.UserService; import cn.itcast.dubbo.domain.User; import cn.itcast.user.mapper.UserMapper; import org.apache.dubbo.config.annotation.DubboService; import org.springframework.beans.factory.annotation.Autowired; @DubboService public class UserServiceImpl implements UserService {<!-- --> @Autowired private UserMapper userMapper; public User queryById(Long id) {<!-- --> return userMapper.findById(id); } }
Add configuration in application.yml
spring: datasource: url: jdbc:mysql://localhost:3306/dubbo-demo?useSSL=false username: root password: root driver-class-name: com.mysql.jdbc.Driver application: name: user-service cloud: nacos: discovery: server-addr: localhost:8848 #Configure dubbo, registration center, exposed ports and protocols, package scanning of dubbo annotations dubbo: protocol: name: dubbo port: 20881 registry: address: spring-cloud://localhost #Use the registration center in SpringCloud scan: base-packages: cn.itcast.user.service #dubbo medium package scanning
4.2.4, service consumers
Introduce dubbo service in OrderController. Call UserService to query users
package cn.itcast.order.controller; import cn.itcast.dubbo.api.UserService; import cn.itcast.dubbo.domain.Order; import cn.itcast.dubbo.domain.User; import cn.itcast.order.service.OrderService; import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("order") public class OrderController {<!-- --> @Autowired private OrderService orderService; @DubboReference private UserService userService; @GetMapping("{orderId}") public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {<!-- --> //Query order by id Order order = orderService. queryOrderById(orderId); // get user id Long userId = order. getUserId(); //query user User user = userService. queryById(userId); //set user object order. setUser(user); // Query the order by id and return return order; } }
Add dubbo configuration in the module of Order-service
spring: application: name: order-service cloud: nacos: discovery: server-addr: localhost:8848 #dubbo configuration dubbo: registry: address: spring-cloud://localhost #Use cloud's registration center consumer: check: false #dubbo has startup check by default retries: 0 #dubbo built-in retry mechanism queryOrderById(orderId); // get user id Long userId = order. getUserId(); //query user User user = userService. queryById(userId); //set user object order. setUser(user); // Query the order by id and return return order; } }
Add dubbo configuration in the module of Order-service
spring: application: name: order-service cloud: nacos: discovery: server-addr: localhost:8848 #dubbo configuration dubbo: registry: address: spring-cloud://localhost #Use cloud's registration center consumer: check: false #dubbo has startup check by default retries: 0 #dubbo built-in retry mechanism