preface
Starting from this chapter, we learn Spring Cloud Alibaba related micro-service components.
Introduction to Spring Cloud Alibaba
Spring Cloud Alibaba is committed to providing a one-stop solution for microservice development. This project contains the necessary components for developing distributed application microservices that developers can easily use to develop distributed application services through the Spring Cloud programming model.
Relying on Spring Cloud Alibaba, Spring Cloud applications can be connected to Ali Micro service solutions by adding some annotations and a small amount of configuration, and distributed application systems can be quickly built through Ali middleware.
Spring Cloud Alibaba features
- Sentinel: Supports access to WebServlet, WebFlux, OpenFeign, RestTemplate, Dubbo, Gateway, and Zuul traffic limiting degradation functions. Traffic limiting degradation rules can be modified in real time through the console at run time, and traffic limiting degradation metrics can be monitored.
- Service Registration and Discovery Nacos: It ADAPTS to the Spring Cloud Service Registration and discovery standard and integrates Ribbon support by default.
- Distributed Configuration Management Nacos: Supports external configuration in distributed systems and automatically refreshes when configuration changes.
- RPC Service Dubbo: Extend Spring Cloud clients RestTemplate and OpenFeign to support calling Dubbo RPC services.
- “Message Driven RocketMQ” : Build message driven capabilities for microservice applications based on Spring Cloud Stream.
- Distributed Transaction Seata: A distributed transaction solution that supports high performance and easy to use.
- Ali Cloud object storage OSS: large-scale, secure, low-cost, highly reliable cloud storage service. Supports storage and access of any type of data in any application anytime, anywhere.
- Distributed Task Scheduling SchedulerX: provides second-level, precise, highly reliable, and highly available scheduled (Cron expression based) task scheduling services. It also provides a distributed task execution model, such as grid tasks. Grid tasks allow quantum tasks to be evenly distributed to all workers (schedulerx-client) for execution.
- “Ali Cloud SMS” : global SMS service, friendly, efficient and intelligent communication capabilities, to help enterprises quickly build customer access channels.
Spring Cloud Alibaba component
Nacos
: Alibaba open source product, a dynamic service discovery, configuration management and service management platform that makes it easier to build cloud native applications.Sentinel
: Lightweight flow control products oriented to distributed service architecture, take traffic as the entry point to protect the stability of services from multiple dimensions such as flow control, fuse downgrading, and system load protection.RocketMQ
: an open source distributed messaging system, based on highly available distributed clustering technology, provides low-latency, highly reliable message publishing and subscription services.Dubbo
Apache Dubbo™ is a high-performance Java RPC framework.Seata
: Alibaba open source product, an easy-to-use high-performance microservice distributed transaction solution.Alibaba Cloud ACM
: An application configuration center that centrally manages and pushes application configurations in a distributed architecture.Alibaba Cloud OSS
: Ali Cloud Object Storage Service (OSS) is a massive, secure, low-cost and highly reliable cloud Storage Service provided by Ali Cloud. You can store and access any type of data in any application, anytime, anywhere.Alibaba Cloud SchedulerX
: A distributed task scheduling product developed by Ali middleware team, which provides second-level, accurate, highly reliable and highly available timed (Cron expression based) task scheduling service.Alibaba Cloud SMS
: Global SMS service, friendly, efficient and intelligent interconnection communication capabilities, help enterprises quickly build customer access channels.
What is a registry
Service registry is the core component of service management. Similar to directory service, it is mainly used to store service information, such as provider URL string and routing information. A service registry is one of the most basic infrastructures in a microservices architecture.
A registry is the “address book” of the microservices architecture, recording the mapping between services and service addresses. In a distributed architecture, services are registered here, and when a service needs to call another service, it finds the address of the service and makes the call.
In the absence of a registry, interservice calls need to know the address of the service caller (written IP :port). Changing the deployment address forces you to change the address specified in the call. After having the registry, each service only needs to know the service name (soft code) when calling others, and the address will be called through the registry according to the service name to obtain the specific service address.
To take a real life example, for example, there are two usage scenarios of the address book in our mobile phone:
❝
When I want to call Zhang SAN, I need to find him by name in the address book, and then I can find his mobile phone number to make a call. — Service discovery
Li Si got his mobile phone number and told me his phone number. I put li Si’s number in the address book, and then I can find him from the address book. — Service registration
Address book –? What role (Service Registry)
❞
Summary: The role of a service registry is to “register services” and “discover services”.
A common registry
- Netflix Eureka
- Alibaba Nacos
- HashiCorp Consul
- Apache ZooKeeper
- CoreOS Etcd
- CNCF CoreDNS
features | Eureka | Nacos | Consul | Zookeeper |
---|---|---|---|---|
CAP | AP | CP + AP | CP | CP |
Health check | Client Beat | TCP/HTTP/MYSQL/Client Beat | TCP/HTTP/gRPC/Cmd | Keep Alive |
Avalanche protection | There are | There are | There is no | There is no |
Automatic logout instance | support | support | Does not support | support |
Access protocol | HTTP | HTTP/DNS | HTTP/DNS | TCP |
Listening to the support | support | support | support | support |
Multi-data center | support | support | support | Does not support |
Synchronization across registries | Does not support | support | support | Does not support |
SpringCloud integration | support | support | support | support |
CAP principle and BASE theory
The principle of CAP
The CAP principle, also known as the CAP theorem, refers to the importance of Consistency, Availability and Partition tolerance in a distributed system.
CAP was proposed by Eric Brewer at PODC 2000. This conjecture was proved to be true two years later and became known as CAP theorem. CAP can’t have all three.
features | theorem |
---|---|
Consistency | Also called data atomicity, the system remains in a consistent state after performing an operation. A distributed system in which all users should read the latest value after a successful update is performed is considered to be highly consistent. This is equivalent to all nodes accessing the same latest copy of data. |
Availability | Each operation can always return a result within a certain amount of time. The words “within a certain amount of time” and “return result” are important here. Within a certain amount of time means that the results are returned within tolerable limits, which can be success or failure. |
Partition tolerance | In the case of network partitioning, the separated nodes can still provide services normally (distributed cluster, data is distributed on different servers, servers can be accessed normally no matter what). |
Trade-off strategy
Only two of the three CAP features can be satisfied, so there are three trade-offs:
- “CA without P” : C (strong consistency) and A (availability) are guaranteed if P (partitioning is not allowed) is not required. However, giving up P means giving up the expansibility of the system, that is, the distributed nodes are limited and cannot deploy child nodes, which is against the original intention of the distributed system design.
- “CP without A” : If A (available) is not required, it means that each request needs to maintain strong consistency between servers, while P (partition) will lead to infinite synchronization time (that is, wait for data synchronization to complete before normal access to the service). Once network failure or message loss occurs, user experience will be sacrificed. Wait for all data to be consistent before allowing users to access the system. In fact, there are many systems designed as CP, the most typical of which is distributed database, such as Redis and HBase. For these distributed databases, data consistency is a fundamental requirement, because if this standard is not met, then simply use a relational database, and there is no need to waste resources deploying a distributed database.
- “AP without C” : To be highly available and allow partitioning, consistency must be abandoned. Once partitioning occurs, nodes may lose contact with each other, and for high availability, each node can only serve with local data, which can lead to global data inconsistencies. A typical application is like the scene of buying up a mobile phone in a certain meter. It may be that there is stock on the page when you browse the product in the first few seconds. When you finish selecting the product and prepare to place an order, the system will prompt you that the order has failed and the product has been sold out. In fact, this is to ensure the normal service of the system in terms of A (availability), and then make some sacrifices in terms of data consistency. Although some user experience will be affected, it will not cause serious congestion in the shopping process of users.
conclusion
Nowadays, for most of the large Internet application scenarios, there are many hosts, scattered deployment, and now the cluster scale is getting larger and larger, the nodes will only be more and more, so node failure, network failure is normal, so the fault tolerance of zoning has become a distributed system must face the problem. So it’s A choice between C and A. However, traditional projects may be different. Take the transfer system of the bank as an example, the consistency of data involving money cannot be compromised at all. C must ensure that it would rather stop service if there is A network failure, and it can make A choice between A and P.
All in all, there is no best strategy, a good system should be architected according to the business scenario, and only the right one is the best.
The BASE theory of
CAP theory has been around for years. Is there really no way to solve this problem? Maybe some changes can be made. For example, C doesn’t have to be so consistent. It can save the data and update it later, achieving what is called “final consistency.”
This idea is a huge problem, which also leads to the second theory, BASE theory.
❝
BASE: Abbreviation for Basically Available, Soft state, and Eventually consistent, coined by the architects of ebay.
❞
BASE theory is the result of tradeoff between consistency and availability in CAP. It is derived from the summary of distributed practice of large-scale Internet and gradually evolved based on CAP theorem. Its core idea is:
❝
Since Strong consistency cannot be achieved, each application can adopt an appropriate method to achieve Eventual consistency according to its own service characteristics.
❞
Basically Available
Basic availability is the ability of a distributed system to allow a partial loss of availability (such as response time, functional availability) in the event of a failure. It is important to note that being basically available is by no means the same as not being available.
- Loss in response time: Normally, the search engine returns the search results to users within 0.5 seconds. However, due to faults (such as power failure or network disconnection in some equipment rooms of the system), the response time of the search results increases to 1 to 2 seconds.
- Loss of functionality: Some consumers may be directed to a degraded page during peak shopping hours (such as Singles’ Day) in order to protect the stability of the system.
Soft state
What is a soft state? In contrast to atomicity, requiring that copies of data across multiple nodes be consistent is a “hard state.”
A soft state is one that allows the system to have intermediate states that do not affect the overall availability of the system. Generally, one copy of data in distributed storage has multiple copies. The delay of data synchronization between different copies is a manifestation of soft state.
Eventually consistent
Systems can’t be soft all the time. There has to be a time limit. After the expiration of the period, data consistency should be guaranteed for all copies. To achieve the final consistency of data. This time frame depends on network latency, system load, data replication scheme design, and so on.
In fact, not only distributed systems use final consistency, but also relational databases use final consistency for certain functions, such as backup and database replication, which take time. During the replication process, the business reads the old value. Of course, data consistency was eventually achieved. This is also a classic case of ultimate consistency.
conclusion
In general, BASE theory is oriented towards large, highly available and scalable distributed systems, which is the opposite of ACID of traditional transactions. It is completely different from ACID’s strong consistency model, but gains availability by sacrificing strong consistency and allows data to be inconsistent for a period of time.
Why do you need a registry
Now that we know what a registry is, let’s move on to why we need one. In distributed systems, there are more complex issues to consider than simply finding a mapping between a service and its address in a registry:
- How can services be discovered after registration
- How can I log out of a service in a timely manner
- How can services scale horizontally effectively
- How to route a service when it is discovered
- How can I degrade a service when it is abnormal
- How can registries make themselves highly available
The resolution of these problems depends on the registry. Registry functions like a DNS server or a load balancer, but in reality, as a basic component of microservices, registries can be more complex and require more flexibility and timeliness. Therefore, we still need to learn more Spring Cloud microservice components to cooperate with application development.
The registry addresses the following issues:
- Service management
- Automatic discovery between services
- Dependency management of services
Nacos introduction
Nacos is an open source tool launched by Alibaba for service discovery and configuration management of distributed systems. Dynamic Naming and Configuration Service, Na /NameServer, CO Configuration, Service indicates that the registry/configuration center is service-centered. Service is a first-class citizen of the Nacos world.
❝
The website says: a dynamic service discovery, configuration management and service management platform that makes it easier to build cloud native applications.
❞
Nacos is dedicated to discovering, configuring, and managing microservices. Nacos provides an easy-to-use feature set to quickly implement dynamic service discovery, service configuration, service metadata, and traffic management.
Nacos makes it more agile and easy to build, deliver, and manage microservices platforms. Nacos is the service infrastructure for building a modern “service” -centric application architecture.
Using Nacos simplifies service discovery, configuration management, service governance, and management solutions, making it easier to discover, manage, share, and compose microservices.
Nacos website: https://nacos.io/zh-cn/
Github:https://github.com/alibaba/nacos
Nacos installation
Environment to prepare
Nacos relies on the Java environment to run. If you build and run Nacos from code and need to configure the Maven environment for this, make sure you install it in one of the following versions:
- The JDK 1.8 +;
- Maven 3.2 x +.
Download the source code or install the package
Nacos can be obtained from both source code and distribution packages.
Source way
Download the source code from Github.
git clone https://github.com/alibaba/nacos.git
cd nacos/
mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U
ls -al distribution/target/
// change the $version to your actual path cd distribution/target/nacos-server-$version/nacos/bin Copy the code
Distribution package
You can download the latest stable version from https://github.com/alibaba/nacos/releases nacos – server package.
Start the server
Linux/Unix/Mac
Start in the Nacos /bin directory.
Startup command (standalone stands for standalone mode, not cluster mode) :
sh startup.sh -m standalone
Copy the code
If you are using Ubuntu or cannot find the error symbol when you run the script, try the following:
bash startup.sh -m standalone
Copy the code
Windows
Start command:
cmd startup.cmd
Copy the code
Or double-click the startup. CMD file to run it.
access
Visit: http://localhost:8848/nacos/, the default username/password is nacos/nacos.
Shut down the server
Linux/Unix/Mac
sh shutdown.sh
Copy the code
Windows
cmd shutdown.cmd
Copy the code
Or double-click the shutdown.cmd file to run it.
An introduction to Nacos
Create a project
We created an aggregation project to illustrate Nacos, starting with a POM parent project.
Add the dependent
pom.xml
<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">
<modelVersion>4.0.0</modelVersion>
<! -- Project coordinate address --> <groupId>com.example</groupId> <! -- Project module name --> <artifactId>nacos-demo</artifactId> <! -- Project Version Name SNAPSHOT version, official version RELEASE --> <version>1.0 the SNAPSHOT</version> <! -- Inherits spring-boot-starter-parent dependency --> <! -- Use inheritance mode, implement reuse, conform to inheritance can be used --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.0. RELEASE</version> </parent> <! --Centrally define dependent component versions without introducing,When a declared dependency is used in a subproject, the version number of the dependency can be omitted.This allows unified management of the dependent versions used in the project --> <properties> <! -- Spring Cloud hoxton.sr4 dependencies --> <spring-cloud.version>Hoxton.SR4</spring-cloud.version> <! -- Spring Cloud Alibaba --> <spring-cloud-alibaba.version>2.1.0. RELEASE</spring-cloud-alibaba.version> </properties> <! Project dependency management The parent project only declares dependencies. The child project needs to specify the required dependencies (omit version information). <dependencyManagement> <dependencies> <! -- Spring Cloud dependencies --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <! -- Spring Cloud Alibaba --> <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> </dependencies> </dependencyManagement> </project> Copy the code
Product-service
Create a project
Create a product-Service project under the parent project.
Add the dependent
Add the spring-cloud-starter-Alibaba-nacos-discovery dependency.
<! -- Spring Cloud Alibaba NacOS Discovery
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
Copy the code
Complete dependencies are as follows:
<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">
<! -- Inheriting parent dependencies --> <parent> <artifactId>nacos-demo</artifactId> <groupId>com.example</groupId> <version>1.0 the SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>product-service</artifactId> <! -- Project dependencies --> <dependencies> <! -- Spring Cloud Alibaba NacOS Discovery <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <! Spring Boot Web dependency --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <! -- Lombok dependency --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> <! -- Spring Boot test 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> </dependencies> </project> Copy the code
The configuration file
application.yml
server:
port: 7070 # port
spring:
application:
name: product-service # app name Configure the Nacos registry cloud: nacos: discovery: enabled: true If you don't want to use Nacos for service registration and discovery, set it to false server-addr: 127.0. 01.: 8848 # Nacos server address Copy the code
Entity class
Product.java
package com.example.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable; @Data @NoArgsConstructor @AllArgsConstructor public class Product implements Serializable { private Integer id; private String productName; private Integer productNum; private Double productPrice; } Copy the code
Write the service
ProductService.java
package com.example.service;
import com.example.pojo.Product;
import java.util.List;
/ * ** Goods and services* / public interface ProductService { / * ** Query the list of goods * * @return * / List<Product> selectProductList(a); } Copy the code
ProductServiceImpl.java
package com.example.service.impl;
import com.example.pojo.Product;
import com.example.service.ProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import java.util.Arrays; import java.util.List; / * ** Goods and services* / @Slf4j @Service public class ProductServiceImpl implements ProductService { / * ** Query the list of goods * * @return * / @Override public List<Product> selectProductList(a) { log.info("Commodity service query commodity information..."); return Arrays.asList( new Product(1.Huawei Mobile.1.5800D), new Product(2."Lenovo Notebook".1.6888D), new Product(3."Xiaomi Tablet".5.2020D) ); } } Copy the code
Control layer
ProductController.java
package com.example.controller;
import com.example.pojo.Product;
import com.example.service.ProductService;
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; import java.util.List; @RestController @RequestMapping("/product") public class ProductController { @Autowired private ProductService productService; / * ** Query the list of goods * * @return * / @GetMapping("/list") public List<Product> selectProductList(a) { return productService.selectProductList(); } } Copy the code
❝
This project can be tested by unit testing, or directly by URL using Postman or browser.
❞
Start the class
Enable service registration discovery through the Spring Cloud native annotation @enableDiscoveryClient.
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// Enable the @enableDiscoveryClient annotation. This annotation is enabled by default in the current version //@EnableDiscoveryClient @SpringBootApplication public class ProductServiceApplication { public static void main(String[] args) { SpringApplication.run(ProductServiceApplication.class, args); } } Copy the code
The registry
Refresh the Nacos server and you can see that the service is registered with Nacos.
Order service order-service
Create a project
Create an order-service project under the parent project.
Add the dependent
pom.xml
<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">
<! -- Inheriting parent dependencies --> <parent> <artifactId>nacos-demo</artifactId> <groupId>com.example</groupId> <version>1.0 the SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>order-service</artifactId> <! -- Project dependencies --> <dependencies> <! -- Spring Cloud Alibaba NacOS Discovery <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <! Spring Boot Web dependency --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <! -- Lombok dependency --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> <! -- Spring Boot test 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> </dependencies> </project> Copy the code
The configuration file
application.yml
server:
port: 9090 # port
spring:
application:
name: order-service # app name Configure the Nacos registry cloud: nacos: discovery: enabled: true If you don't want to use Nacos for service registration and discovery, set it to false server-addr: 127.0. 01.: 8848 # Nacos server address Copy the code
Entity class
Product.java
package com.example.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable; @Data @NoArgsConstructor @AllArgsConstructor public class Product implements Serializable { private Integer id; private String productName; private Integer productNum; private Double productPrice; } Copy the code
Order.java
package com.example.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable; import java.util.List; @Data @NoArgsConstructor @AllArgsConstructor public class Order implements Serializable { private Integer id; private String orderNo; private String orderAddress; private Double totalPrice; private List<Product> productList; } Copy the code
Consumer services
OrderService.java
package com.example.service;
import com.example.pojo.Order;
public interface OrderService {
/ * ** Query orders based on primary keys * * @param id * @return * / Order selectOrderById(Integer id); } Copy the code
There are three ways to realize service consumption:
- DiscoveryClient: Obtains service information through metadata
- LoadBalancerClient: Load balancer for the Ribbon
- LoadBalanced: Enable load balancer in the Ribbon with annotations
DiscoveryClient
Spring Boot does not provide any auto-configured RestTemplate Beans, so you need to inject RestTemplate into the Boot class.
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate; // Enable the @enableDiscoveryClient annotation. This annotation is enabled by default in the current version //@EnableDiscoveryClient @SpringBootApplication public class OrderServiceApplication { @Bean public RestTemplate restTemplate(a) { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } } Copy the code
OrderServiceImpl.java
package com.example.service.impl;
import com.alibaba.fastjson.JSON;
import com.example.pojo.Order;
import com.example.pojo.Product;
import com.example.service.OrderService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.web.client.RestTemplate; import java.util.List; @Slf4j @Service public class OrderServiceImpl implements OrderService { @Autowired private RestTemplate restTemplate; @Autowired private DiscoveryClient discoveryClient; / * ** Query orders based on primary keys * * @param id * @return * / @Override public Order selectOrderById(Integer id) { log.info("Order service query order information..."); return new Order(id, "order-001"."China".22788D, selectProductListByDiscoveryClient()); } private List<Product> selectProductListByDiscoveryClient(a) { StringBuffer sb = null; // Get the list of services List<String> serviceIds = discoveryClient.getServices(); if (CollectionUtils.isEmpty(serviceIds)) return null; // Get the service by the service name List<ServiceInstance> serviceInstances = discoveryClient.getInstances("product-service"); if (CollectionUtils.isEmpty(serviceInstances)) return null; // Build the remote service invocation address ServiceInstance si = serviceInstances.get(0); sb = new StringBuffer(); sb.append("http://" + si.getHost() + ":" + si.getPort() + "/product/list"); log.info("Order service invokes goods service..."); log.info("The commodity service address obtained from the registry is: {}", sb.toString()); // Call the service remotely // ResponseEntity: encapsulates the returned data ResponseEntity<List<Product>> response = restTemplate.exchange( sb.toString(), HttpMethod.GET, null. new ParameterizedTypeReference<List<Product>>() {}); log.info("Product information query result: {}", JSON.toJSONString(response.getBody())); return response.getBody(); } } Copy the code
LoadBalancerClient
OrderServiceImpl.java
package com.example.service.impl;
import com.alibaba.fastjson.JSON;
import com.example.pojo.Order;
import com.example.pojo.Product;
import com.example.service.OrderService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.List; @Slf4j @Service public class OrderServiceImpl implements OrderService { @Autowired private RestTemplate restTemplate; @Autowired private LoadBalancerClient loadBalancerClient; // Ribbon Load balancer / * ** Query orders based on primary keys * * @param id * @return * / @Override public Order selectOrderById(Integer id) { log.info("Order service query order information..."); return new Order(id, "order-001"."China".22788D, selectProductListByLoadBalancerClient()); } private List<Product> selectProductListByLoadBalancerClient(a) { StringBuffer sb = null; // Get the service by the service name ServiceInstance si = loadBalancerClient.choose("product-service"); if (null == si) return null; sb = new StringBuffer(); sb.append("http://" + si.getHost() + ":" + si.getPort() + "/product/list"); log.info("Order service invokes goods service..."); log.info("The commodity service address obtained from the registry is: {}", sb.toString()); // ResponseEntity: encapsulates the returned data ResponseEntity<List<Product>> response = restTemplate.exchange( sb.toString(), HttpMethod.GET, null. new ParameterizedTypeReference<List<Product>>() {}); log.info("Product information query result: {}", JSON.toJSONString(response.getBody())); return response.getBody(); } } Copy the code
@LoadBalanced
The @loadBalanced load balancing annotation is added when the class is started to inject the RestTemplate to indicate that the RestTemplate has client-side load balancing capability on request.
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @EnableDiscoveryClient @SpringBootApplication public class OrderServiceApplication { @Bean @LoadBalanced // Load balancing annotations public RestTemplate restTemplate(a) { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } } Copy the code
OrderServiceImpl.java
package com.example.service.impl;
import com.alibaba.fastjson.JSON;
import com.example.pojo.Order;
import com.example.pojo.Product;
import com.example.service.OrderService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.List; @Slf4j @Service public class OrderServiceImpl implements OrderService { @Autowired private RestTemplate restTemplate; / * ** Query orders based on primary keys * * @param id * @return * / @Override public Order selectOrderById(Integer id) { log.info("Order service query order information..."); return new Order(id, "order-001"."China".22788D, selectProductListByLoadBalancerAnnotation()); } private List<Product> selectProductListByLoadBalancerAnnotation(a) { String url = "http://product-service/product/list"; log.info("Order service invokes goods service..."); log.info("The commodity service address obtained from the registry is: {}", url); // ResponseEntity: encapsulates the returned data ResponseEntity<List<Product>> response = restTemplate.exchange( url, HttpMethod.GET, null. new ParameterizedTypeReference<List<Product>>() {}); log.info("Product information query result: {}", JSON.toJSONString(response.getBody())); return response.getBody(); } } Copy the code
Control layer
OrderController.java
package com.example.controller;
import com.example.pojo.Order;
import com.example.service.OrderService;
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; / * ** Query orders based on primary keys * * @param id * @return * / @GetMapping("/{id}") public Order selectOrderById(@PathVariable("id") Integer id) { return orderService.selectOrderById(id); } } Copy the code
access
Refresh the Nacos server and you can see that the service is registered with Nacos.
Visit: http://localhost:9090/order/1 the results are as follows:
Configuring the MySQL Database
Nacos prior to version 0.7 used an embedded database, Apache Derby, to store data by default (the embedded database started with Nacos without additional installation). Support for MySQL data sources was added in version 0.7 and later.
MySQL data source
Environment requirements: MySQL 5.6.5+ (You are advised to use the production database in active/standby mode or a high availability database);
Initialize the MySQL database
Create the database nacOS_config.
SQL source file address: https://github.com/alibaba/nacos/blob/master/distribution/conf/nacos-mysql.sql, or on nacos – decompression under the conf directory server, Find the nacos-mysql.sql file and run it as follows:
Application. The properties configuration
Modify nacos/conf/application. The properties file of the following content.
The final modification result is as follows:
#*************** Config Module Related Configurations ***************# ### If user MySQL as datasource: # specify the data source for MySQL spring. The datasource. Platform = MySQL
Count of DB:
Number of database instances
db.num=1
ServerTimezone =Asia/Shanghai if MySQL 8.0+ is used
Connect URL of DB:
Copy the code
Db. Url. 0 = JDBC: mysql: / / 127.0.0.1:3306 / nacos_config? characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&serverTimezone=Asia/Shanghai db.user=root db.password=1234
❝
If, like me, you use MySQL 8.0+, you’ll get an error when you start Nacos. Add 8.0+ mysql-connector-java-8.0.xx.jar and restart Nacos. The driver-class of MySQL has been changed.
❞
❝
In the next article, we will explain how to set up a cluster environment for the Nacos registry
❞
This article is licensed under a Creative Commons attribution – Noncommercial – No Deductive 4.0 International license.
You can see more articles about Spring Cloud in the category.
🤗 your likes and retweets are the biggest support for me.
📢 Scan code pay attention to Mr. Hallward “document + video” each article is equipped with a special video explanation, learning more easily oh ~