Architectural features of microservices
-Single responsibility: Micro services have smaller granularity, and each service corresponds to a unique business capability to achieve a single responsibility
-Autonomy: team independence, technology independence, data independence, independent deployment and delivery
-Service oriented: services provide a unified standard interface, independent of language and technology
-Strong isolation: do a good job in isolation, fault tolerance and degradation of service calls to avoid cascading problems
summary
-Monomer architecture: simple and convenient, highly coupled, poor scalability, suitable for small projects. For example: student management system
-Distributed architecture: loose coupling and good scalability, but the architecture is complex and difficult. Suitable for large Internet projects, such as Jingdong and Taobao
-Microservice: a good distributed architecture scheme
① Advantages: smaller splitting granularity, more independent services and lower coupling
② Disadvantages: the architecture is very complex, making it more difficult to operate, monitor and deploy
-Spring cloud is a one-stop solution for microservice architecture, integrating various excellent microservice functional components
Service splitting and remote invocation
Service splitting principle
-Different microservices should not develop the same business repeatedly
-The microservice data is independent. Do not access the databases of other microservices
-Microservices can expose their business as interfaces for other microservices to call
Service split example
Cloud Demo: parent project, management dependency
-Order service: order micro service, which is responsible for order related businesses
-User service: user micro service, responsible for user related business
requirement:
-Both order microservices and user microservices must have their own databases and be independent of each other
-Both order service and user service expose Restful interfaces
-If the order service needs to query user information, it can only call the Restful interface of the user service, not the user database
Register RestTemplate
First, we register the RestTemplate instance in the OrderApplication startup class in the order service:
Implement remote call
Modify the queryOrderById method in the OrderService class under the cn.itcast.order.service package in the order service service:
Provider and consumer
In the service invocation relationship, there are two different roles:
Service provider: a service called by other micro services in a business. (provide interfaces to other microservices)
Service consumer: Service in one business calling other micro services. (call interfaces provided by other microservices)
A service can be either a service provider or a consumer.
Eureka registryQuestion 1: how does the order service know the user service instance address?
The process of obtaining address information is as follows:
-After the user service instance is started, register its own information with Eureka server (Eureka server). This is called service registration
-Eureka server saves the mapping relationship between service name and service instance address list
-Order service pulls the instance address list according to the service name. This is called service discovery or service pull
Question 2: how does order service select a specific instance from multiple user service instances?
-Order service selects an instance address from the instance list using the load balancing algorithm
-Make a remote call to the instance address
Q3: how does the order service know whether a user service instance is still healthy and has been down?
-The user service will send a request to Eureka server at regular intervals (30 seconds by default) to report its status, which is called heartbeat
-When no heartbeat is sent after a certain period of time, Eureka server will consider the microservice instance as faulty and remove it from the service list
-When the order service pulls the service, the fault instance can be eliminated
Build Eureka server
Create Eureka server service
First of all, let's register the service side of the center: Eureka server, which must be an independent microservice
Introducing eureka dependency
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
Write startup class
package com.zxq.eureka; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer @SpringBootApplication public class EurekaApplication { public static void main(String[] args){ SpringApplication.run(EurekaApplication.class,args); } }
Write configuration file
Write an application.yml file as follows:
server: port: 10086 spring: application: name: eureka-server eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka
Start service
Start the microservice and access it in the browser: http://127.0.0.1:10086
Service registration
Introduce dependency
In the pom file of user service, introduce the following Eureka client dependency:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
configuration file
In user service, modify the application.yml file and add the service name and eureka address:
spring: application: name: userservice eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka
Service pull and load balancing
Finally, we need to pull the instance list of user service from Eureka server and realize load balancing. Modify the queryOrderById method in the OrderService class under the cn.itcast.order.service package in the order service service. Modify the url path of access, and replace ip and port with service name:
In the OrderApplication of order service, add a @ LoadBalanced annotation to the RestTemplate Bean:
Ribbon load balancing
Custom load balancing policy
By defining IRule, you can modify load balancing rules in two ways:
1. Code method: define a new IRule in the OrderApplication class in order service:
2. Configuration file method: add a new configuration in the application.yml file of order service, or modify the rules:
userservice: # Configure load balancing rules for a microservice. Here is the userservice service ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # Load balancing rules
Starvation loading
By default, the Ribbon uses lazy loading, that is, the LoadBalanceClient will be created during the first access, and the request time will be very long.
Hungry loading will be created when the project is started to reduce the time-consuming of the first access. Hungry loading can be started through the following configuration:
ribbon: eager-load: enabled: true clients: userservice
summary
1.Ribbon load balancing rules
The rule interface is IRule
The default implementation is ZoneAvoidanceRule. Select the service list according to the zone, and then poll
2. Custom load balancing method
Code method: the configuration is flexible, but it needs to be repackaged and published when modifying
Configuration method: intuitive and convenient. There is no need to repackage and publish, but global configuration cannot be done
3. Starvation loading
Turn on hungry loading
Specifies the name of the loaded microservice
Nacos registry
The service is registered with nacos
Nacos is a component of spring cloud Alibaba, which also follows the service registration and service discovery specifications defined in spring cloud. Therefore, there is not much difference between using Nacos and using Eureka for microservices.
Introduce dependency
Introduce the dependency of SpringCloudAlibaba in ` < dependencymanagement > 'in the pom file of the cloud demo parent project:
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.6.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency>
Then introduce the Nacos discovery dependency into the pom files in user service and order service:
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
Configure nacos address
Add the nacos address in application.yml of user service and order service:
spring: cloud: nacos: server-addr: localhost:8848
Service hierarchical storage model
Configure cluster for user service
Modify the application.yml file of user service and add the cluster configuration:
spring: cloud: nacos: server-addr: localhost:8848 discovery: cluster-name: HZ # Cluster name
We copy a user service startup configuration again and add the following attributes:
-Dserver.port=8083 -Dspring.cloud.nacos.discovery.cluster-name=SH
Load balancing with cluster priority
Modify the application.yml file of order service and add the cluster configuration:
spring: cloud: nacos: server-addr: localhost:8848 discovery: cluster-name: HZ # Cluster name
Modify load balancing rules
Modify the application.yml file of order service and modify the load balancing rules:
userservice: ribbon: NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # Load balancing rules
Cross cluster access
Weight configuration
No access when weight is 0 (can be used for upgrade)
Environment isolation - namespace
Configure the namespace for the microservice
At this time, access the order service. Because the namespace is different, the userservice will not be found, and the console will report an error:
The difference between Nacos and Eureka
The service instances of Nacos are divided into two l types:
-Temporary instance: if the instance goes down for more than a certain period of time, it will be removed from the service list. The default type is.
-Non temporary instance: if an instance goes down, it will not be removed from the service list. It can also be called a permanent instance.
Not culled
Nacos configuration managementUnified configuration management
Add profile in nacos
Pull configuration from microservice
Introducing Nacos config dependency
First, in the user service service, the client dependency of Nacos config is introduced:
<!--nacos Configuration management dependency--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
Add bootstrap.yaml
Then, add a bootstrap.yaml file in user service, as follows:
spring: application: name: userservice # Service name profiles: active: dev #Development environment, this is dev cloud: nacos: server-addr: localhost:8848 # Nacos address config: file-extension: yaml # File suffix
Configure hot update
Mode 1:
Mode 2:
Use the @ ConfigurationProperties annotation instead of the @ Value annotation.
In the user service service, add a class and read the pattern.dateformat attribute:
Use this class in UserController instead of @ Value:
Configure sharing
Add an environment sharing configuration
We add a userservice.yaml file in nacos:
In the user service, modify the PatternProperties class and read the newly added attributes:
In the user service, modify the UserController and add a method:
Run two userapplications with different profile s
Configure shared priorities
Feign remote call
Introduce dependency
We introduce feign dependency in pom file of order service service:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
adding annotations
Add annotations to the startup class of order service to enable Feign
Write Feign's client
Create a new interface in order service, as follows
test
Custom configuration
Modifying the log level of feign based on the configuration file can be for a single service
feign: client: config: userservice: # Configuration for a micro service loggerLevel: FULL # log level
It can also be for all services
feign: client: config: default: # default here is the global configuration. If the service name is written, it is the configuration for a micro service loggerLevel: FULL # log level
There are four levels of logs:
-NONE: no log information is recorded, which is the default value.
-BASIC: only record the requested method, URL, response status code and execution time
-HEADERS: on the basis of BASIC, additional header information of request and response is recorded
-FULL: records the details of all requests and responses, including header information, request body and metadata.
You can also modify the log level based on Java code, first declare a class, and then declare an object of Logger.Level:
public class DefaultFeignConfiguration { @Bean public Logger.Level feignLogLevel(){ return Logger.Level.BASIC; // The log level is BASIC } }
If you want to * * take effect globally * *, put it in the @ EnableFeignClients annotation of the startup class:
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class)
If it is * * partially effective * *, put it in the corresponding @ FeignClient annotation:
@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class)
Feign usage optimization
Feign initiates http requests at the bottom, which depends on other frameworks. Its underlying client implementation includes:
• URLConnection: it is implemented by default and does not support connection pool
• Apache HttpClient: supports connection pooling
• OKHttp: support connection pool
Introduce dependency
<!--httpClient Dependence of --> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> </dependency>
Configure connection pool
feign: client: config: default: # default global configuration loggerLevel: BASIC # At the log level, BASIC is the BASIC request and response information httpclient: enabled: true # Enable feign's support for HttpClient max-connections: 200 # Maximum connections max-connections-per-route: 50 # Maximum connections per path
In conclusion, Feign's Optimization:
1. Try to use basic for log level
2. Use HttpClient or OKHttp instead of URLConnection
① Introduce feign httpclient dependency
② The configuration file enables the httpClient function and sets the connection pool parameters
Best practices
Inheritance mode
The same code can be shared through inheritance:
1) Define an API interface, define methods, and make declarations based on spring MVC annotations.
2) Feign client and Controller have integrated interface
advantage:
-Simple
-Code sharing is realized
Disadvantages:
-Tight coupling between service providers and service consumers
-The annotation mapping in the parameter list does not inherit, so the method, parameter list and annotation must be declared again in the Controller
Extraction mode
Extract Feign's Client as an independent module, and put the POJO related to the interface and the default Feign configuration into this module for all consumers to use.
Gateway service gatewayCore functions and features of gateway:
-Request routing
-Permission control
-Current limiting
gateway quick start
Next, we will demonstrate the basic routing function of the gateway. The basic steps are as follows:
1. Create the SpringBoot project gateway and introduce the gateway dependency
2. Write startup class
3. Write basic configuration and routing rules
4. Start the gateway service for testing
Create a gateway service and introduce dependencies
<!--gateway--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--nacos Service discovery dependency--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
Write startup class
@SpringBootApplication public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } }
Write basic configuration and routing rules
server: port: 10010 # Gateway port spring: application: name: gateway # Service name cloud: nacos: server-addr: localhost:8848 # nacos address gateway: routes: # Gateway routing configuration - id: user-service # Routing id, user-defined, as long as it is unique # uri: http://127.0.0.1: the destination address of 8081 # route http is the fixed address uri: lb://The target address lb of userservice # route is load balancing, followed by the service name predicates: # Routing assertion is to judge whether the request meets the conditions of routing rules - Path=/user/** # This is matched according to the path. It meets the requirements as long as it starts with / user /
Assertion factory
The assertion rules we write in the configuration file are just strings. These strings will be read and processed by the predict factory and transformed into conditions for routing judgment
For example, Path=/user / * * matches according to the path. This rule is determined by
`org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory ` class
There are more than a dozen assertion factories like this in the spring cloud gateway:
Filter factory
Gateway filter is a filter provided in the gateway, which can process the requests entering the gateway and the responses returned by the microservice:
Spring provides 31 different routing filter factories. For example:
Default filter
If you want to be effective for all routes, you can write the filter factory to default. The format is as follows:
spring: cloud: gateway: routes: - id: user-service uri: lb://userservice predicates: - Path=/user/** default-filters: # Default filter - AddRequestHeader=Truth, helloworld
Global filter
The global filter is also used to handle all requests and microservice responses entering the gateway, just like the gateway filter. The difference is that the gateway filter is defined by configuration, and the processing logic is fixed; The logic of GlobalFilter needs to be implemented by writing code.
Custom global filter
@Order(-1) @Component public class AuthorizeFilter implements GlobalFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 1. Get request parameters MultiValueMap<String, String> params = exchange.getRequest().getQueryParams(); // 2. Get the authorization parameter String auth = params.getFirst("authorization"); // 3. Calibration if ("admin".equals(auth)) { // Release return chain.filter(exchange); } // 4. Interception // 4.1. Prohibit access and set the status code exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN); // 4.2. End processing return exchange.getResponse().setComplete(); } }
Filter execution sequence
The request to enter the gateway will encounter three types of filters: the filter of the current route, DefaultFilter and GlobalFilter
After requesting a route, the current route filter, DefaultFilter and GlobalFilter will be merged into a filter chain (Collection), and each filter will be executed in turn after sorting
What are the sorting rules?
-Each filter must specify an order value of type int. the smaller the * * order value, the higher the priority and the higher the execution order * *.
-GlobalFilter specifies the order value by implementing the Ordered interface or adding the @ order annotation, which is specified by ourselves
-The order of routing filter and defaultFilter is specified by Spring. By default, it is incremented from 1 in the order of declaration.
-When the order value of the filter is the same, it will be executed in the order of defaultfilter > routing filter > globalfilter.
Cross domain problem
What is a cross domain problem
Cross domain: domain name inconsistency is cross domain, mainly including:
-Domain names are different: www.taobao.com and www.taobao.org and www.jd.com and miaosha.jd.com
-The domain name is the same, but the port is different: localhost:8080 and localhost8081
Cross domain problem: the browser prohibits cross domain ajax requests between the initiator of the request and the server, and the request is intercepted by the browser
Solve cross domain problems
In the application.yml file of the gateway service, add the following configuration
spring: cloud: gateway: # . . . globalcors: # Global cross domain processing add-to-simple-url-handler-mapping: true # Solve the problem that the options request is intercepted corsConfigurations: '[/**]': allowedOrigins: # Which websites are allowed to make cross domain requests - "http://localhost:8090" allowedMethods: # Allowed cross domain ajax request mode - "GET" - "POST" - "DELETE" - "PUT" - "OPTIONS" allowedHeaders: "*" # Header information allowed to be carried in the request allowCredentials: true # Allow cookie s maxAge: 360000 # Validity of this cross domain detection