1. Prepare the Registry (Nacos)

1. Introduction to Nacos

Nacos is the middleware of the microservice registry and configuration center launched by Ali. Nacos project address github.com/alibaba/nac… You can pull down your project from Git and use MVN to compile and package it. Here’s how to package and start Nacos.

2. Compile, package and run Nacos

ⅰ. Pull items

Directly in the terminal input: git clone https://github.com/alibaba/nacos.git

ⅱ. Switch to a stable version branch

Check the project Tags, it shows that 1.3.2 is the last release, so we need to switch the local code to the 1.3.2 tag, go to the project root directory and type the command:Git Checkout -b 1.3.2 1.3.2.

Iii. Compile and package projects using MVN

Enter the package command in the project root directory: mvn-prelease -nacos -DskipTests clean install -u-drat. skip=true

ⅳ. Start Nacos

After successfully packing, nacos-server-1.3.2.zip and nacos-server-1.3.2.tar.gz will be generated in the directory \ nacos-distribution-target. We just need to copy them to the deployment directory and decompress them. Enter the startup. CMD -m standalone command in the bin directory on the terminal.

ⅴ, starting effect

After the terminal is started, port 8848 is displayed and the content path is’/nacOS ‘. In this case, nacOS is successfully started. The diagram below:When we visithttp://127.0.0.1:8848/nacos/#/login, you can get the following login interface:Then enter the username and password (nacos/nacos) to go to the service management interface:You can see the menu of configuration management, service management and other functions on the interface, so nacOS is successfully started. The management side of NACOS is very convenient to use. You can add, delete, modify and check service configurations on the interface, and manage service providers and subscribers visually.

3. Other configurations of Nacos

I. Configure DB to implement data persistence

In nacOS conf, there is an application. Properties file. This file is the configuration file of the project. If we wanted to use a database to store nacOS data, we could modify the following code in this file:

...
### If use MySQL as datasource:
spring.datasource.platform=mysql
### Count of DB:
db.num=1
### Connect URL of DB:
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
### 数据库用户名
db.user=root
### 数据库密码
db.password=1315977663
...
Copy the code

Then we create a nacOS database and execute the nacos-mysql.sql script in conf. You get the following tables:

Once the database is ready, let’s reboot nacOS and add a configuration to the admin interface to see if the data is logged.

Two, build each module

Once the registry Nacos is ready, you can start building project modules. I’ll take a simple project as an example, creating a user module, an order module, a generic parent module, and a project root module. The user module acts as the producer of the service, and the order module is the subscriber (the two are called each other, and the identity is mutual), so that the two can access the distributed service through the registry. The universal parent module is the parent dependency of all modules, which is used to configure the universal MVN dependencies required by all modules and manage the versions of each dependency uniformly. Finally, the project root module is the root directory of the project, which will import all sub-modules in the project for unified packaging, compilation and management. In addition, there are service gateway module, process management module and so on. The project catalog is as follows:



1. Root module (CCM-root)

Root module is mainly used for unified management, packaging and compilation of various modules in the project, so that the project sub-modules are organized together. This module is also the root directory of the project. The component method is relatively simple, just need to wear an empty folder, add the following POM files:

<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > The < modelVersion > 4.0.0 < / modelVersion > < groupId > com. FBL < / groupId > < artifactId > CCM - root < / artifactId > < version > 1.0 < / version > <name> CCM-root </name> <description> Root project </description> <packaging> POM </ Packaging > <modules> <! Ccm-user </module> <! Ccm-order </module> <! <module> ccM-parent </module> <! Service gateway module --> <module> CCM-gateway </module> <! Ccm-process </module> </modules> </project>Copy the code

The content of the module node under Modules in the XML file is the name of each module in the project. Organizing the project in this way also has the advantage that all modules can be automatically imported into the editor when IDEA imports the project.

2. Universal parent module (CCM-parent)

The main function of the generic parent module is to introduce dependencies that other modules need, and to unify the management of dependency versions in the project. This module is the parent of all other modules in the project, and the child module automatically inherits the dependencies it introduces, and can define versions of the dependencies so that all module dependencies are consistent. The build POM for this module is as follows:

<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > < the parent > <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> < version > 2.3.3. RELEASE < / version > < relativePath / > <! -- lookup parent from repository --> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.fbl</groupId> < artifactId > CCM - parent < / artifactId > < version > 0.0.1 - the SNAPSHOT < / version > < name > CCM - parent < / name > < packaging > pom < / packaging > <! <properties> <java.version>1.8</java.version> <! - https://start.spring.io/actuator/info corresponds to the version information on this site looking for - > < spring. Cloud. Version > Hoxton. SR8 < / spring. Cloud. Version > < spring cloud. Alibaba. Version > 2.2.0. RELEASE < / spring. Cloud. Alibaba. Version > < / properties > <! All dependencies introduced in dependencies are inherited by submodules. > <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>RELEASE</version> </dependency> </dependencies> <! - dependencyManagement will not automatically inherit past dependencies in submodules. Instead, it needs to be reintroduced in submodules, where the version number is no longer required. -- > <! The general thing to do here is to manage the version of dependencies, specify the version of all dependencies in the project, and keep the version consistent when submodules are introduced without specifying the version. --> <dependencyManagement> <dependencies> <! -- all this dependence can guarantee the son module org. Springframework. Cloud related rely on version consistent - > < the dependency > < groupId > org. Springframework. Cloud < / groupId > <artifactId>spring-cloud-dependencies</artifactId> <version>${spring.cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <! > <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring.cloud.alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.activiti</groupId> < artifactId > activiti - engine < / artifactId > < version > 6.0.0 < / version > < / dependency > < the dependency > < the groupId > org. Activiti < / groupId > < artifactId > activiti - spring < / artifactId > < version > 6.0.0 < / version > < / dependency > <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> < version > 2.1.3 < / version > < / dependency > < the dependency > < groupId > com. Alibaba < / groupId > < artifactId > druid - spring - the boot - starter < / artifactId > < version > 1.1.23 < / version > < / dependency > < the dependency > < the groupId > mysql < / groupId > < artifactId > mysql connector - Java < / artifactId > < version > 8.0.21 < / version > < / dependency > </dependencies> </dependencyManagement> </project>Copy the code

< span style = “box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; font-size: 14px! Important; word-break: inherit! Important;” Dependencies introduced in dependencyManagement are not automatically inherited in the submodule, but must be reintroduced in the submodule without specifying the version number. The general thing to do here is to manage the version of dependencies, specify the version of all dependencies in the project, and keep the version consistent when submodules are introduced without specifying the version. Once you have the dependency file, just create a folder in your project, put the file in it, and add

ccM-parent

under the module node of the CCM-root poM file. This completes the construction of the generic parent module.

3. Order Module (CCM-Order)

The previous two modules are built to pave the way for the following building modules, starting from the order module is the real obligation meaning of the module. We will learn how to register services in nacOS and how to use the configuration in NACOS. Here’s how to build this module, starting with the POM file.

ⅰ. Create poM files

<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" > < modelVersion > 4.0.0 < / modelVersion > < the parent > < groupId > com. The FBL < / groupId > < artifactId > CCM - parent < / artifactId > The < version > 0.0.1 - the SNAPSHOT < / version > < relativePath / > <! -- lookup parent from repository --> </parent> <artifactId>ccm-order</artifactId> <name>ccm-order</name> <description> Order module </description> <dependencies> <! <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <! --> <dependency> <groupId>com.alibaba. Cloud </groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <! > <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <! <dependency> <groupId>org.mybatis.spring. Boot </groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <! > <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> </dependency> <! --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> </dependencies> <build> <plugins> <! -- Introducing the SpringBoot packaging plug-in. > <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>Copy the code

As the comment code in the POM file above states: * We did not specify the version of all dependencies because the specified module of this module has already specified the version. * Common dependencies such as spring-boot-starter, spring-boot-starter, and lombok are not introduced in this module, but can still be used in this module (you’ll see how they work later). This is because the module automatically inherits its parent module’s dependencies. Spring-cloud-starter-alibaba-nacos-discovery is a dependency on nacOS service discovery and registration. Spring-cloud-starter-alibaba-nacos-config adds dependencies to the NACOS configuration center. * Other dependencies are commented in the code above.

ⅱ. Create a directory for the module

The directory interface is shown below:



In fact, the project structure and Spring Boot project check is not much. Among them:

    providerPut is the external service interface;

Register the service with Nacos

Add the registry address and application name configuration to the application.yml file. The configuration is as follows:

Name: Order Cloud: nacos: Discovery: # registry address server-addr: 127.0.0.1:8848 config: # server-addr: ${spring.cloud.nacos.discovery.server-addr}Copy the code

Add @enableDiscoveryClient annotation to SpringBoot startup class to enable service registration and discovery. The code is as follows:

package com.fbl.order; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @enableDiscoveryClient @mapperscan (basePackages = "com.fbl.order.mapper") public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); }}Copy the code

Write a service provider (OrderProvidertest.java). By writing a RestController, we can register the service with Nacos. The code is as follows:

package com.fbl.order.provider; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @restController@requestMapping ("orderProviderTest") @refreshScope public class orderProviderTest @value ("${user.name}") private String name; @value ("${user.age}") private String age; @getMapping ("test") public String test () {return "order "+ age + name; }}Copy the code

Spring Cloud is a call between micro services based on Http protocol, so we register the service is similar to writing Web interface; However, Dubbo is a call between micro Services realized based on RPC protocol. Generally speaking, RPC protocol calls remote methods after serialization of parameters, and then returns the results to the caller after serialization. Based on this feature, Dubbo registration service is a registered Services class. This is similar to registering a bean in the Spring container.



Now that Spring Cloud has registered the service with Nacos, let’s start the Order module and Nacos to see what happens.



The effect of the console after the order module is started:



Open the registry to see:



Let’s try accessing the order module service:

We haven’t seen the call between services yet, so don’t worry, we’ll get to that when we create the user module.

Use and manage the configuration of Nacos

An important concept in microservices is the registry, whose responsibility is to uniformly manage the configuration of services and reduce the operation and maintenance costs of microservices. Nacos integrates with the configuration center by default and makes it easy to modify and update the configuration in the admin interface. Let’s try using Nacos’s configuration center. In application, yml file to add the registry’s address configuration, namely spring. Cloud. Nacos. Config. Server – addr. I showed you the code before when configuring the registry and I won’t post it here. Add the default initial configuration to application.yml as follows:

user:
  username: zhangsan
  age: 654
Copy the code

Use the configuration in our OrderProviderTest service provider class as follows:

package com.fbl.order.provider; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; restController@requestMapping ("orderProviderTest") // The RefreshScope annotation enables dynamic refresh of the configuration. Otherwise, the configuration will not refresh after the configuration is changed in the configuration center. @refreshScope public class OrderProviderTest {${user.username} @value ("${user.username}") private String name; @Value("${user.age}") private String age; @getMapping ("test") public String test () {return "order "+ age + name; }}Copy the code

Start the order module and see what the configuration looks like:

Add a configuration to nacOS to change the configuration in the project, as shown below:

In nacOS, username and age have been changed.

At this point, the use of the configuration center is also demonstrated, and interested readers can continue to explore the configuration of multi-environment switching.

4. User module (CCM-user)

Now build the user module (CCM-User), which calls the services of the order module. Here we will learn about the calls between the two services.

ⅰ. Create poM files

<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > < the parent > < the groupId > com. FBL < / groupId > < artifactId > CCM - parent < / artifactId > < version > 0.0.1 - the SNAPSHOT < / version > < relativePath / > < / parent > < modelVersion > 4.0.0 < / modelVersion > < artifactId > CCM - user < / artifactId > < name > CCM - user < / name > <description> <description> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <! -- User has more dependencies than order, For service discovery and call - > < the dependency > < groupId > org. Springframework. Cloud < / groupId > <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>Copy the code

Compared to Order,user has more spring-cloud-starter-OpenFeign dependencies for service discovery and invocation.

ⅱ. Build the directory of user module



In fact, the structure of the project and the order project are not found. Among them:

    consumerIt is to mobilize consumers of other services;

Iii. Write UserConsumerTest to consume other services

The user project configuration file and the bootstrap class annotations and the ORDER module are not so bad that I won’t repeat them here. Let’s go straight to the process of writing a service consumer with the following code:

package com.fbl.user.consumer; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.RequestMapping; @feignClient (name = "order") public interface UserConsumerTest {// Register with spring container @service // invoke the Service interface @feignClient (name = "order") public interface UserConsumerTest {// @requestMapping ("orderProviderTest/test") String orderProviderTestRemote(); }Copy the code

@feignClient (name = “order”), @requestMapping (“orderProviderTest/test”); This makes you a consumer of the orderProviderTest/ Test service and registers it in the Spring container for other classes to call.

Use UserConsumerTest

Now we just need to write a service that injects UserConsumerTest to use the service of the Order module. Specific operations are as follows:

package com.fbl.user.provider; import com.fbl.user.consumer.UserConsumerTest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("userProviderTest") public class UserProviderTest { @Autowired private UserConsumerTest userConsumerTest; @ GetMapping (" test ") public String test () {return "user module call:" + userConsumerTest. OrderProviderTestRemote (); }}Copy the code

Now let’s call the service of the user module and see if we can call the service of the Order module. The effect is as follows:

It is clear that we have the data returned by the order module service, indicating that the call between services is ready.

Third, summary

Build microservice project based on Spring Cloud and Nacos has been completed here, all the above code is available at gitee.com/fangbl/cclo… . There are many microservice solutions, but the core content is always the same (registry, configuration center, service gateway, fuse, service producer, service consumer). Among many solutions, Spring Cloud Alibaba provided by Alibaba is quite good (it is already one of the recommended solutions on the official website of Spring Cloud), among which the Nacos registry is an important component. Nacos supports both Spring Cloud and Dubbo, and those interested can use Nacos in Dubbo projects. I will post another post on microservices projects, focusing on building process engine modules, building service gateways, using fuses, etc.