[It’s really annoying, why do you always have to add new businesses, fortunately, I used the microservice SpringCloud, and it was easy to handle (Part 1)]

It’s really annoying, why do I always need to add new business, fortunately I used the microservice SpringCloud, it’s easy to handle

The concept of microservices

The so-called microservice is actually an architectural approach.

Let me give you an example. We used to create SpringBoot projects, right? In this SpringBoot project, we often wrote a lot of business functions, such as we need to create entity classes that map a large number of data tables, and then create about these entity classes. The classes of the data access layer (dao) are used to encapsulate their CRUD and other functions. Then create business logic layer (service) classes related to entity classes to implement their specific business logic methods, etc. We put all the businesses to be created in one project for implementation, which is a centralized architecture method , is an architectural approach with high coupling and low development efficiency.

Of course, if the business volume is small, there is no problem in adopting a centralized architecture. However, once the business volume increases sharply, the coupling between functions becomes higher and higher, which is not conducive to later maintenance. So microservices came into being.

The microservice architecture, as the name suggests, means that each service is built based on a single business. To put it simply, one business in a project runs in its own independent process. Each service can be implemented using different programming languages as well as different data storage technologies.

Characteristics of microservices

Single responsibility: Each service in the microservice corresponds to a unique business and achieves a single responsibility.
Service-oriented: Each service must expose the service interface API to the outside world, and does not care about the technical implementation and programming language of the service, as long as the REST interface is used.
Autonomy and independence: Services do not interfere with each other and do not affect each other.

The relationship between SpringCloud and microservices

Spring Cloud is currently the most mainstream technology in the microservice architecture.

As for why mainstream? As mentioned in my previous blog, because SpringCloud is also one of the projects under Spring, and Spring also has SpringBoot under Spring, SpringBoot is precisely because of its advantages of being able to quickly build a Spring application, so it has made SpringCloud , and SpringCloud also drives SpringBoot. At the same time, SpringCloud is also good at integration. It can take all suitable frameworks and integrate them into its own projects, and can integrate very popular technologies together. For example: configuration management, service discovery, intelligent routing, load balancing, fuses, control bus, cluster status, etc.

How to use Spring Cloud

1. Create a parent project and add dependencies

In microservices, multiple projects need to be created, so first create a parent project on this basis, and subsequent projects will use this project as the parent, using Maven’s aggregation and inheritance to uniformly manage the versions and configurations of sub-projects.

After creating the parent project, add the following dependencies:

 <groupId>org.example</groupId>
    <artifactId>SpringCloudA</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    
    <modules>
        <module>UserService</module>
        <module>consumerDemo</module>
        <module>eurekaServer</module>
        <module>lxsGateway</module>
    </modules>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
        <mapper.starter.version>2.1.5</mapper.starter.version>
        <mysql.version>5.1.46</mysql.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- springCloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${<!-- -->spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- Generic Mapper Launcher -->
            <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>${<!-- -->mapper.starter.version}</version>
            </dependency>
            <!-- mysql driver -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${<!-- -->mysql.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

It should be noted here that the versions of SpringCloud and SpringBoot must correspond.
The corresponding relationship between SpringCloud and SoringBoot versions is as follows:
Hoxton 2.2.x.RELEASE
Greenwich 2.1.x.RELEASE
Finchley 2.0.x.RELEASE
Edgware 1.5.x.RELEASE
Dalston 1.5.x.RELEASE

We are now using the Greenwich version of SpringCloud and the 2.1.5.RELEASE version of SpringBoot.

2. Create a sub-project: service provider

A service provider is used to provide external services.
We now create a service that provides query users, select the parent project, and create a SpringBoot subproject.

Add the following dependencies:

 <parent>
        <artifactId>SpringCloudA</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>UserService</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Generic Mapper Launcher -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
        </dependency>
        <!-- mysql driver -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>

Writing configuration files

After the addition is complete, write the configuration file and configure the data source, port, Mybatis scanning package and other information. application.yml is as follows:

server:
  port: 9091
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud
    username: root
    password: 1234

  application:
    name: userService
mybatis:
  type-aliases-package: com.xx.user.pojo

Code writing of User business functions

Create the entity class User that maps the data table. I omitted this step. You can create it according to your own data table.
Then there is the Mapper mapping interface. I also omitted this step. You can see what I wrote about Mybatis-plus earlier.
Then create the Service class, the code is as follows:

@Service
public class UserService {<!-- -->

    @Resource
    private UserMapper userMapper;

    public User queryById(Long id){<!-- -->
        return userMapper. selectByPrimaryKey(id);
    }
}

The last is the Controller class, pay attention to provide a REST interface to the outside world.
code show as below:

@RestController
@RequestMapping("user")
public class UserController {<!-- -->

    @Resource
    private UserService userService;

    @GetMapping("{id}")
    public User queryById(@PathVariable Long id){<!-- -->
        return userService. queryById(id);
    }
}

Well, the project business function of a service provider is written here, just one business, which is to provide the business of querying users.

3. Create a sub-project: service consumer

The service consumer, as the name implies, its business is to access the services provided by the service provider.
The first is to create a project, and then add dependencies.

Add the following dependencies

<parent>
        <artifactId>SpringCloudA</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>consumerDemo</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    <dependencies>

After the dependencies are added. It’s time to create the access business.

Code writing for consumer services

First, you need to inject the RestTemplate class into the starter class. This class encapsulates the Http-based client and realizes the serialization and deserialization of objects and json, which is very convenient. The injection code is as follows:

@Bean
public RestTemplate restTemplate(){<!-- -->
return new RestTemplate();
}

Then create an entity class, which does not need to map the data table, but is only used to implement object serialization. This step is omitted.
Then create a controller class to access the services provided by the service provider.
code show as below:

@RestController
@RequestMapping("/consumer")
public class ConsumerController {<!-- -->
@Autowired
private RestTemplate restTemplate;
\t
@GetMapping("/{id}")
public User queryById(@PathVariable Long id){<!-- -->
String url = "Http://localhost:9091/user/" + id;
return restTemplate.getForObject(url, User.class);
}
}

Test

Start the service provider sub-project first, then start the service consumer sub-project, and then visit the address of the service consumer: http://localhost:8080/consume/1, and then visit the service provider address http://localhost: Data provided by 9091/user/1.

Fourth, create a sub-project: Eureka service registration

The role of service registration

After the above service provider and service consumer are created and tested, have you found anything wrong?

The problem is that the service consumer needs to know the service address provided by the service provider accurately. If the address of the service provided by the service provider needs to be changed in the future, the service consumer also needs to change it in time, otherwise it is easy to report an error. This is not a problem when there are few services, but once there are more, a project splits into dozens or hundreds of microservices. If you still use this method at this time, it will be very troublesome to maintain in the future .

At this time, the Eureka registration center is required to register the services provided by all service providers, so that service consumers do not need to find services by themselves, but directly tell Eureka their needs, and then Eureka directly tells the services according to the provided needs. service consumers. At the same time, Eureka and the service provider will also be monitored through the heartbeat mechanism. Once a service provider has a problem, Eureka will remove it from the service list.

Thus, Eureka service registration realizes service registration, discovery, monitoring and other functions for us.

Create a Eureka sub-project and add dependencies as follows:

<parent>
        <artifactId>SpringCloudA</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>eurekaServer</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

Writing configuration files

Mainly write ports and Eureka service addresses.

server:
  port: 10086

spring:
  application:
    name: eurekaServer
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka
  server:
    # Do not register yourself
register-with-eureka: false
# Do not pull services
fetch-registry: false

How does the service provider register the provided service with Eureka

Add Eureka client dependency

First, add dependencies to the service provider sub-project, mainly to add Eureka client dependencies; automatically register the service to the EurekaServer service address list.
Add dependencies as follows:

<!-- Eureka client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
Add @EnableDiscoveryClient to enable Eureka client discovery

Just add it to the startup class of the service provider subproject.

Writing configuration files

1. Add the Spring.application.name attribute to specify the application name, which will be used as the id of the application in the future.
2. Add the eureka.client.service-url.defaultZone property to specify the registered Eureka service address.
Add the following to the configuration file of the service provider subproject:

server:
  port: 9091
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud
    username: root
    password: 1234

  application:
    name: userService
mybatis:
  type-aliases-package: com.xx.user.pojo

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

Well, at this point, the service provider has successfully registered the service.

How do service consumers tell Eureka the services they need

Add Eureak client dependency, add @EnableDiscoveryClient annotation

These two steps are the same as the above steps, but they are operated in the service consumer sub-project.

Modify configuration

Configure the configuration file of the service consumer sub-project as follows:

spring:
  application:
    name: consumerDemo

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka
Use the method of DiscoveryClient class to get the service instance according to the service name.

In the controller class of the service consumer subproject, create a DiscoveryClient class, and obtain a service instance according to the service name.
Modify the code as follows:

@RestController
@RequestMapping("/consumer")
public class ConsumerController {<!-- -->
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
\t
@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id) {<!-- -->
List<ServiceInstance> serviceInstances = discoveryClient.getInstances("userService");
ServiceInstance serviceInstance = serviceInstances. get(0);
String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/user/"
+ id;
return restTemplate.getForObject(url, User.class);
}
}

Well, at this point, the service consumer tells Eureka the required service, and obtains the final service address through the service name.

Of course, there is no need to manually obtain the ip and port. If you find it troublesome, you can also call it directly through the service name. like:

@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id) {<!-- -->
String url = "http://userService/user/" + id;
return restTemplate.getForObject(url, User.class);
}

Follow

SpringCloud also has many components, such as: load balancing Ribbon, fuse Hystrix, service call Feign, etc.
Due to limited space, it is reserved for the next issue.