1, Preparatory work
1. Create configuration center
Create a moudle for spring boot
Select Eureka Server
Modify pom.xml file
<?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"> <parent> <artifactId>springcloud1</artifactId> <groupId>com.drhj</groupId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.drhj</groupId> <artifactId>sp05-eureka</artifactId> <version>0.0.1-SNAPSHOT</version> <name>sp05-eureka</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
application.yml configuration
Because at present, it is only for a single server. It does not register with itself or pull from itself. So turn off self-protection mode
spring: application: name: eureka-server server: port: 2001 #Turn off self-protection mode #host name #For a single server, do not register with yourself or pull from yourself eureka: server: enable-self-preservation: false instance: hostname: eureka1 client: register-with-eureka: false fetch-registry: false
- eureka cluster servers are distinguished by hostname
- eureka.server.enable-self-preservation
eureka's self-protection status: does the rate of heartbeat failure exceed 85% within 15 minutes? If it exceeds, Eureka Server will protect the current instance registration information and prompt a warning. Once in the protection mode, Eureka Server will try to protect the information in its service registry and will not delete the data in the service registry. That is, no micro services will be logged off - eureka.client.register-with-eureka=false
Do not register with yourself - eureka.client.fetch-registry=false
Do not pull registration information from itself - eureka.instance.lease-expiration-duration-in-seconds
After the last heartbeat, how long is the interval between determining that the microservice is unavailable? 90 by default
Add @ EnableEurekaServer
Add in startup class
package com.drhj.sp05; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer @SpringBootApplication public class Sp05EurekaApplication { public static void main(String[] args) { SpringApplication.run(Sp05EurekaApplication.class, args); } }
Start test
localhost:2001
There is no service registration at present
Modify the hosts file and add eureka domain name mapping
If you want to access through a special domain name, such as eureka, you can modify the hosts file,
Location: C:\Windows\System32\drivers\etc\hosts
Please open it as an administrator and use Notepad to open it.
add mapping
Start test
supplement
eureka's four operating mechanisms
1. When the client starts, it will repeatedly connect to the registry and try to register until the registration is successful
2. The client sends heartbeat data every 30s. If the server fails to receive the heartbeat of a service for three consecutive times, its registration information will be deleted
3. The client pulls the registry every 30s and refreshes the local registry cache
4. Self protection mode
Within 15 minutes, 85% of servers have abnormal heartbeat
Due to network interruption, 85% of servers have abnormal heartbeat within 15 minutes and automatically enter the protection mode
In self-protection mode, all registration information will not be deleted
Automatically exit the protection mode after network recovery
During development and debugging, the protection mode can be turned off to avoid affecting debugging
2. Registration services
Add dependencies in pom.xml
Add eureka client dependencies in the pom.xml of itemservice userservice orderservice respectively
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
Add settings in application.yml
Add settings in application.yml of itemservice userservice orderservice and specify the access address
eureka: client: service-url: # eureka servers in different locations can be purchased from cloud service providers # Your own server can only write defaultZone defaultZone: http://eureka1:2001/eureka
3. Registration test
1) Start three services
2) Start registry
3) Visit eureka1:2001
Error reported in service item
Error reported in registry
The above two phenomena are normal. Because we do not configure the cluster, port 8761 is started by default. If this port is occupied, an error will be reported, but our test will not be affected.
2, eureka and service provider high availability
High availability means that a service is opened with multiple ports (multiple services), and then selected from these services when calling the service.
1. Set high availability for service providers
Here, set item service high availability for goods and services
Set two servers and specify port 80018002 respectively
Then copy the previous copy
Start the two services respectively to view the registry
Two services appear
2.eureka high availability
Add profile profiles for both servers
application-eureka1.yml
eureka: instance: hostname: eureka1 client: register-with-eureka: true #The configuration of the profile overrides the public configuration fetch-registry: true #The configuration of the profile overrides the public configuration service-url: defaultZone: http://Eureka2: register with eureka2 when Eureka #eureka1 starts in 2002 / 2002
application-eureka2.yml
eureka: instance: hostname: eureka2 client: register-with-eureka: true #The configuration of the profile overrides the public configuration fetch-registry: true #The configuration of the profile overrides the public configuration service-url: defaultZone: http://Eureka1: register with eureka1 at #eureka2 startup in 2001 / Eureka
Configure startup parameters -- spring.profiles.active and -- server.port
Set eureka1 startup parameters
–spring.profiles.active=eureka1 --server.port=2001
Set eureka2 startup parameters
–spring.profiles.active=eureka2 --server.port=2002
Copy previous
Start separately and view
3, Feign remote call
Feign integrates Ribbon, which realizes load balancing and retry by default
1. Business requirements
In order service, you can call item service and user service
2.Feign dependency
Add the following dependencies in the pom.xml file
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
3. Write Feign interface of itemservice
package com.drhj.sp04.feign; import cn.drhj.sp01.pojo.Item; import cn.drhj.web.util.JsonResult; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import java.util.List; /* Configure three: - Which service is called - Which road force - What parameters are submitted to the path */ @FeignClient(name = "item-service") public interface ItemClient { @GetMapping("/{orderId}") JsonResult<List<Item>> getItems(@PathVariable String orderId); @PostMapping("/decreaseNumber") JsonResult<?> decreaseNumber(@RequestBody List<Item> items); }
4. Write the Feign interface of userservice
package com.drhj.sp04.feign; import cn.drhj.sp01.pojo.User; import cn.drhj.web.util.JsonResult; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestParam; @FeignClient(name = "user-service") public interface UserClient { @GetMapping("/{userId}") JsonResult<User> getUser(@PathVariable("userId") Integer id); @GetMapping("/{userId}/score") // 8/score?score=1000 JsonResult<?> addScore(@PathVariable Integer userId,@RequestParam("score") Integer score); }
5. Modify OrderServiceImpl
Add use of remote calls
package com.drhj.sp04.service; import cn.drhj.sp01.pojo.Item; import cn.drhj.sp01.pojo.Order; import cn.drhj.sp01.pojo.User; import cn.drhj.sp01.service.OrderService; import cn.drhj.web.util.JsonResult; import com.drhj.sp04.feign.ItemClient; import com.drhj.sp04.feign.UserClient; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Slf4j @Service public class OrderServiceImpl implements OrderService { @Autowired private ItemClient itemClient; @Autowired private UserClient userClient; //Get order based on order id @Override public Order getOrder(String orderId) { log.info("Get orders, orderId = " + orderId); Order order = new Order(); order.setId(orderId); //Call the user remotely to obtain user information JsonResult<List<Item>> items = itemClient.getItems(orderId); //Remotely call the product to get the product list // order.setItems(); JsonResult<User> user = userClient.getUser(8); order.setUser(user.getData()); order.setItems(items.getData()); return order; } //Add order @Override public void addOrder(Order order) { log.info("Add order: " + order); //Remote call of goods to reduce inventory itemClient.decreaseNumber(order.getItems()); //Remote call users to increase points userClient.addScore(order.getUser().getId(),1000); } }
6. Add comments to the startup class
7. Test
Use this URL to refresh several times
Use the URL to refresh several times to see the background messages of the two itemservice services
8001 port:
8002 port:
Thus, load balancing is realized
4, Ribbon's retry
1. Introduction
Retry refers to sending a request to the server again when the request to access the server fails. If a server fails to retry, the server can be replaced
2. Mechanism
If the remote call fails, you can automatically initiate a retry call
- abnormal
- Server downtime
- Background service blocking timeout
3. Parameters
- MaxAutoRetries - number of retries for a single server. The default is 0
- MaxAutoRetriesNextServer - the number of server changes is 1 by default
- ReadTimeout - timeout to wait for a response. The default is 1000
- OkToRetryOnAllOperations - whether to retry all types of requests. By default, only GET requests are retried
- ConnectTimeOut - the waiting timeout for establishing a connection with the background server. The default is 1000
4. Test
1) Add the configuration in application.yml in the order service. The configuration is set in the order service because the request is sent to the item service through the request of the order service
ribbon: MaxAutoRetries: 1 MaxAutoRetriesNextServer: 2
Set the number of retries for a single server to 1. If the retries are not successful, replace the server and the number of times to replace the server is 2
2) Add random blocking code to the controller in itemservice to block artificially
package com.drhj.sp02.controller; import cn.drhj.sp01.pojo.Item; import cn.drhj.sp01.service.ItemService; import cn.drhj.web.util.JsonResult; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Random; @RestController @Slf4j public class ItemController { @Autowired private ItemService itemService; //Get the order item list according to the order id @GetMapping("/{orderId}") public JsonResult<List<Item>> getItems(@PathVariable String orderId) throws InterruptedException { List<Item> items = itemService.getItems(orderId); //Random blocking, 90% probability of executing blocking code if (Math.random() < 0.9) { //Pause [0.5000) ms int t = new Random().nextInt(5000); System.out.println("Pause:" + t); Thread.sleep(t); } return JsonResult.ok().data(items); } //reduce stock //@RequestBody receives the request protocol body data completely @PostMapping("/decreaseNumber") public JsonResult<?> decreaseNumber(@RequestBody List<Item> items) { itemService.decreaseNumber(items); return JsonResult.ok().msg("Inventory reduction successful"); } @GetMapping("/favicon.ico") public void ico() { } }
3) Restart the two services of item and the order service
Continue visit http://localhost:8201/1
View item background
8001 port
8002 port
A retry occurred
Note that this is the result of multiple refreshes, which may not be intuitive, but it can be seen that a retry did occur.