SpringCloud
The project source code written during the learning of the whole spring cloud: git@gitee.com:HumorChen/spring-cloud-parent.git
The last blog was: eureka (service governance) Step by step screenshot of Eureka learning notes of spring cloud service registration discovery (service governance) (with the source code project written during learning)
Download the git project above before reading this blog.
Getting to know Spring Cloud
What is micro service
- The word "Microservices" comes from Martin Fowler's blog post called Microservices, which can be found on his official blog
http://martinfowler.com/articles/microservices.html - Microservice is a design style of system architecture. Its main purpose is to split an originally independent system into multiple small services. These small services run in their own independent processes. Services generally communicate and cooperate through HTTP RESTfuLAPI.
- Each small service is built around one or more business functions with high coupling in the system, and each service maintains white data storage, business development automation test cases and independent deployment mechanism.
Introduction to spring cloud
-
spring cloud is an ordered collection of a series of frameworks
-
spring cloud does not manufacture wheels repeatedly. It just combines the more mature and practical frameworks developed by various companies
-
Repackaging in Spring Boot style shields the complex configuration and implementation principles, and finally leaves a set of simple, easy to understand, easy to deploy and easy to maintain distributed system development kit for developers
-
Taking advantage of the development convenience of Spring Boot, it cleverly simplifies the development of distributed system infrastructure, such as service registration and discovery, configuration center, message bus, load balancing, circuit breaker, data monitoring, etc., which can be started and deployed with one click with the development style of Spring Boot.
-
The naming method of Spring Cloud version adopts the name of London underground station, and corresponds to the version time order according to the alphabet. For example, the earliest Release version is Angel, the second Release version is Brixton, and then Camden, Dalton, Edgware, Finchley,Greenwich and Hoxton
-
Correspondence between spring cloud version and springboot version
Spring Cloud vs. Dubbo
- Both Spring Cloud and Dubbo are effective tools for implementing microservices.
- Dubbo only implements service governance, while the Spring Cloud subproject covers many components under the micro service architecture.
- Dubbo uses RPC communication protocol and Spring Cloud uses RESTful to complete communication. Dubbo is slightly more efficient than Spring Cloud.
Summary
- Microservice is to split each module of the project into an architecture design style that can be run, deployed and tested independently.
- Spring company integrates the components commonly used in microservice architecture in other companies, and uses SpringBoot to simplify its development and configuration. Called Spring Cloud
- Both Spring Cloud and Dubbo are effective tools for implementing microservices. Dubbo has better performance and Spring Cloud is more comprehensive.
Feign declarative service invocation
Feign introduction
- Feign is a declarative REST client. It uses interface based annotation to facilitate client configuration.
- Feign was initially provided by Netflix, but does not support spring MVC annotations. Later, it was encapsulated by spring cloud and supports spring MVC annotations, making it easier for users to accept.
Feign usage steps
- Introduce open feign on the consumer side
- Write Feign call interface by dependency
- Add the @ EnableFeignClients annotation in the startup class to enable the Feign function
- Test call
-
Start a previous Eureka server, port 8761.
-
Create two modules, one is feign consumer and the other is feign provider. Copy the previous consumer and provider codes respectively. To modify the configuration, delete the 8762 eureka server in server rul
-
Start provider
-
Introducing the openfeign dependency in the consumer project
<!-- feign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
-
Annotate the consumer startup class with @ EnableFeignClients
package com.fpa.consumer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableEurekaClient @EnableDiscoveryClient @EnableFeignClients public class ConsumerApp { public static void main(String[] args) { SpringApplication.run(ConsumerApp.class,args); } }
-
Create an interface to declare the interface to call
@FeignClient(value = "provider app") this value is the name of the called service application passed
The interface defined below is actually similar to the interface defined by the service provider. Only the getmapping parameter complements the uri prefix of / goods
@GetMapping("/goods/{id}") public Goods findOne(@PathVariable("id") int id);
//Service provider original @GetMapping("/{id}") public Goods findOne(@PathVariable("id") int id){ return goodsService.findOne(id); }
Complete code
package com.fpa.consumer.interfaces; import com.fpa.consumer.bean.Goods; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient(value = "provider-app") public interface GoodsFeignClient { @GetMapping("/goods/{id}") public Goods findOne(@PathVariable("id") int id); }
-
Interface provided by consumer before modification
package com.fpa.consumer.controller; import com.fpa.consumer.bean.Goods; import com.fpa.consumer.interfaces.GoodsFeignClient; 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("/goods") public class OrderController { /** * Inject the goods feign client interface we just wrote (it doesn't matter if idea is popular) */ @Autowired private GoodsFeignClient goodsFeignClient; @GetMapping("/findGoodsById/{id}") public Goods findOne(@PathVariable("id") int id) { Goods goods = goodsFeignClient.findOne(id); return goods; } }
- Start the consumer and use postman to test the interface successfully
Feign timeout configuration
Feign bottom layer relies on ribbon to realize load balancing and remote invocation. Ribbon defaults to 1 second timeout
- Add sleep to the provider interface, sleep for two seconds, and then return
package com.fpa.provider.controller; import com.fpa.provider.bean.Goods; import com.fpa.provider.service.GoodsService; 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("/goods") public class GoodsController { @Autowired private GoodsService goodsService; @GetMapping("/{id}") public Goods findOne(@PathVariable("id") int id){ try { Thread.sleep(2000); }catch (Exception e){} return goodsService.findOne(id); } }
-
When the interface is called again, an error is reported from the consumer, and the reading timeout occurs
java.net.SocketTimeoutException: Read timed out
-
Go to the application of the consumer project to uniformly configure the ribbon timeout
spring: profiles: active: dev application: name: consumer-app #Set the timeout for the Ribbon ribbon: connectTimeout: 1000 #The connection timeout is 1s by default ReadTimeout: 3000 #The timeout of logical processing is 1s by default
-
Restart the consumer and test the interface with postman. After waiting for 2 seconds, the result is returned
Feign logging
-
Feign can only record debug level log information.
logging: level: com.fpa: debug
-
Define Feign log level Bean
@Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; }
-
Enable this Bean:
@Feignclient(configuration = xxxConfig.class)
-
Modify the consumer's configuration file application yml
spring: profiles: active: dev application: name: consumer-app #Set the timeout for the Ribbon ribbon: connectTimeout: 1000 #The connection timeout is 1s by default ReadTimeout: 3000 #The timeout of logical processing is 1s by default # Configure feign log level, and only debug is allowed logging: level: com.fpa: debug
-
Create FeignLogConfig configuration class
package com.fpa.consumer.config; import feign.Logger; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * Configure Feign log */ @Configuration public class FeignLogConfig { @Bean public Logger.Level level(){ return Logger.Level.FULL; } }
-
Go to GoodsFeignClient to start logging
@FeignClient(value = "provider-app",configuration = FeignLogConfig.class)
package com.fpa.consumer.interfaces; import com.fpa.consumer.bean.Goods; import com.fpa.consumer.config.FeignLogConfig; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient(value = "provider-app",configuration = FeignLogConfig.class) public interface GoodsFeignClient { @GetMapping("/goods/{id}") public Goods findOne(@PathVariable("id") int id); }
-
Restart the consumer and use the postman provider to view the console
2021-08-07 15:23:15.752 DEBUG 4676 --- [nio-9000-exec-1] c.f.c.interfaces.GoodsFeignClient : [GoodsFeignClient#findOne] <--- HTTP/1.1 200 (2199ms) 2021-08-07 15:23:15.752 DEBUG 4676 --- [nio-9000-exec-1] c.f.c.interfaces.GoodsFeignClient : [GoodsFeignClient#findOne] content-type: application/json;charset=UTF-8 2021-08-07 15:23:15.752 DEBUG 4676 --- [nio-9000-exec-1] c.f.c.interfaces.GoodsFeignClient : [GoodsFeignClient#findOne] date: Sat, 07 Aug 2021 07:23:15 GMT 2021-08-07 15:23:15.752 DEBUG 4676 --- [nio-9000-exec-1] c.f.c.interfaces.GoodsFeignClient : [GoodsFeignClient#findOne] transfer-encoding: chunked 2021-08-07 15:23:15.752 DEBUG 4676 --- [nio-9000-exec-1] c.f.c.interfaces.GoodsFeignClient : [GoodsFeignClient#findOne] 2021-08-07 15:23:15.753 DEBUG 4676 --- [nio-9000-exec-1] c.f.c.interfaces.GoodsFeignClient : [GoodsFeignClient#findOne] {"id":1,"title": "Huawei mobile phone", "price":5999.0} 2021-08-07 15:23:15.753 DEBUG 4676 --- [nio-9000-exec-1] c.f.c.interfaces.GoodsFeignClient : [GoodsFeignClient#findOne] <--- END HTTP (46-byte body)