SpringCloud components (1)-simple analysis and testing

SpringCloud components (1)-simple analysis and testing

1 Overview

1.1 Architecture diagram

  • Gateway, configuration center config, circuit breaker, service registration, link tracking, service discovery, one-time token, global lock, leader election, distributed session, cluster status

1.2 Version relationship

1.3 Coding issues

  • If a comment is added to the yaml file of the project, be sure to change the file encoding to utf-8, the default is the system encoding gbk

2 Eureka (service registration and discovery)

2.1 Overview

  • Service governance

  • In the traditional RPC remote call framework, managing the dependencies between each service and the services is more complicated, and the management is more complicated. It is necessary to use service governance to manage the dependencies between services, which can achieve service invocation, load balancing, fault tolerance, and service registration. Find

  • Service registration discovery

    • There is a registry in service registration and discovery. When the server starts, it will register its own server information such as service address and communication address to the registry in an alias manner, and the other party (as a consumer) will change the alias to register Obtain the actual service communication address on the center, and then implement local RPC calls
  • Euerka architecture and Dubbo architecture

2.2 Single Euerka

2.2.1 Server

  • rely

    • Note that the added dependency is spring-cloud-starter-netflix-eureka-server, indicating that it is a client
    < Dependency > < the groupId > org.springframework.cloud </the groupId > < the artifactId > Spring-Cloud-Starter-Netflix-Eureka-Server </the artifactId > </dependency > copy the code
  • Enable Euerka registry function

    @EnableEurekaServerCopy code
  • Configuration file

    • eureka.instance.hostname specifies the host address as the client's registered address (no longer specified by ip)

    • The function of the service name spring.application.name is that when a cluster is created, all servers in the cluster can use the same service name for load balancing

    server: port: 8001 #Specify the running port spring: application: name: eureka-server #Specify the service name eureka: instance: hostname: localhost #Specify the host address client: fetch-registry: false #Specify whether to obtain services from the registry ( no need to open registry) the Register-with-Eureka: false # specify whether you want to register to the registration center (no need to open registry) Server: enable-Self-Preservation: false # turn off Protected mode copy the code
    • enable-self-preservation When the protection mode is turned off, there will be a corresponding prompt when accessing the server homepage

2.2.2 Client

  • rely

    • Note that the added dependency is spring-cloud-starter-netflix-eureka-client, indicating that it is the server
    • Note that spring-boot-starter-web must be introduced, otherwise the client registration failure will be reported, and the error code is 204
    < dependency > < groupId > org.springframework.cloud </groupId > < artifactId > spring-cloud-starter-netflix-eureka-client </artifactId > </dependency > < Dependency > < the groupId > org.springframework.boot </the groupId > < the artifactId > Spring-Boot-Starter-Web </the artifactId > </dependency > copy the code
  • Indicates Eureka client

    @EnableDiscoveryClient copy the code
  • Configuration file

    • The defaultZone will not prompt, you need to fill it in manually. Note that you need to add a space before the yaml format value
    • localhost represents the eureka.instance.hostname of the server
    server: port: 8101 #Run port number spring: application: name: eureka-client #Service name eureka: client: register-with-eureka: true #Register to Eureka's registration center fetch-registry: true #Get a list of registered instances service -url: defaultzone: HTTP://localhost: 8001/Eureka/ # configure registry address copy the code

2.3 Cluster Edition

2.3.1 Server

  • The original eureka-server server adds two configuration files, application-replica1.yml and application-replica2.yml to configure two registries

  • application-replica1.yml

    • Compared with the stand-alone version, first eureka.client adds serviceUrl.defaultZone, and the corresponding value is another registry. Obviously, the same is not ip, but eureka.instance.hostname.
    • Modified fetch-registry and register-with-eureka to true, because now the server also needs to register with each other
    server: port: 8002 spring: application: name: eureka-server eureka: instance: hostname: replica1 client: serviceUrl: defaultZone: http://replica2:8003/eureka/#Register to another Eureka registry fetch-registry: true Eureka-with-the Register: to true copy the code
    server: port: 8003 spring: application: name: eureka-server eureka: instance: hostname: replica2 client: serviceUrl: defaultZone: http://replica1:8002/eureka/#Register to another Eureka registry fetch-registry: true Eureka-with-the Register: to true copy the code
  • Modify the host file

    • Used to map the IP address of the service name
    127.0.0.1 replica1 127.0.0.1 replica2 Copy code
  • Run the cluster

    • Note: There is no need to add two services again, you can start the same springboot application by using different configuration files

    • Copy two configurations started with different configuration files from the original startup configuration

2.3.2 Client

  • Configuration file

    • Also add an additional configuration file application-replica.yml, so that the springboot application will start by copying the configuration file

    • DefaultZone adds two registration centers at the same time, separated by commas

      server: port: 8102 spring: application: name: eureka-client eureka: client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://replica1:8002/eureka/,http://Replica2: 8003/Eureka/ # simultaneously registered with two registry copy the code

2.4 Eureka registration center adds certification

2.4.1 Create a new module and add dependencies

  • eureka-security-server

    • What is introduced here is spring-boot-starter-security, not spring-cloud-security
    < dependency > < groupId > org.springframework.cloud </groupId > < artifactId > spring-cloud-starter-netflix-eureka-server </artifactId > </dependency > < Dependency > < the groupId > org.springframework.boot </the groupId > < the artifactId > Spring-Security-Boot-Starter </the artifactId > </dependency > copy the code

2.4.2 Configuration file

  • spring.security.user to configure the login username and password, instead of reading directly from the database (the disadvantage is that the account and password are fixed)
server: port: 8004 spring: application: name: eureka-security-server security: #Configure SpringSecurity login user name and password user: name: macro password: 123456 eureka: instance: hostname: localhost client: fetch-registry: false register-with -eureka: false copy the code

2.4.3 Configure Spring Security

  • By default, each request to add SpringSecurity dependent applications needs to add a CSRF token to access, and it will not be added when the Eureka client is registered, so you need to configure the/eureka/** path without the CSRF token

  • CSRF
    • Cross-site request forgery - is an attack method that coerces users to perform unintentional operations on the currently logged-in web application
    • The attacker uses some technical means to deceive the user s browser to visit a website that he has authenticated and perform some operations (such as sending emails, sending messages, and even property operations such as transferring money and purchasing goods). Because the browser has been authenticated, so The visited website will be considered as a real user operation and run
    • Take advantage of a loophole in user authentication in the web: simple authentication can only ensure that the request is sent from a user's browser, but cannot guarantee that the request itself is voluntarily sent by the user
@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure (HttpSecurity http) throws Exception { http.csrf().ignoringAntMatchers( "/eureka/**" ); super .configure(http); } } Copy code
  • Login is required when re-requesting the Eureka client

2.4.4 eureka-client registers to the registration center with login authentication

  • eureka-client creates a new configuration file application-security.yml and copies a startup configuration to start with this file

    • The format of defaultZone is changed to http://username:{username}: {password}@hostname:{hostname}: {port}/eureka/
    server: port: 8103 spring: application: name: eureka-client eureka: client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://macro:123456@localhost:8004/eureka/ Copy code

2.5 Eureka common configuration

eureka: client: #eureka client configuration register-with-eureka: true #Whether to register yourself on the eureka server fetch-registry: true #Whether to get the list of services registered on the eureka server service-url: defaultZone: http://localhost:8001/eureka/ # Specify the registration center address enabled: true # Enable the eureka client registry-fetch-interval-seconds: 30 #Define the time interval to get the service list from the eureka server eureka server instance: #eureka client instance configuration lease-renewal-interval-in-seconds: 30 #Define how long the service will go to the registration center to renew lease-expiration-duration-in-seconds: 90 #Define how long the service will not be renewed to consider the service as invalid metadata-map: zone: jiangsu # Hostname of the region : localhost # service host name of the prefer-ip-address: false # whether as a priority with the ip host name Server: #eureka server configuration enable-Self-Preservation: false # close protection mechanism eureka server-side copy the code

3 Ribbon (service call for load balancing)

3.1 Overview

  • Ribbon mainly provides load balancing functions for inter-service calls and API gateway forwarding, and connects between services based on a certain rule (simple polling, random connection)

3.2 Use RestTemplate to implement service invocation

  • RestTemplate is an HTTP client, which can conveniently call the HTTP interface and supports GET, POST, PUT, DELETE and other methods

3.2.1 Get request

  • Get the result of the response from the requested address, the type of the return value of the request, and the request parameters
<T> T getForObject (String url, Class<T> responseType, Object... uriVariables) ; <T> ResponseEntity<T> getForEntity (String url, Class<T> responseType, Object... uriVariables) ; Copy code

3.2.2 Post request

  • Get the response result from the requested address, post submitted form (encapsulated object), return value type, and request parameters
<T> T postForObject (String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) ; <T> ResponseEntity<T> postForEntity (String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) ; Copy code

3.3 Ribbon test

3.3.1 The called module (user-service)

  • rely

    • Register to the Eureka registry
    < dependency > < groupId > org.springframework.cloud </groupId > < artifactId > spring-cloud-starter-netflix-eureka-client </artifactId > </dependency > < dependency > < groupId > org.springframework.boot </groupId > < artifactId > spring-boot-starter-web </artifactId > </dependency > copy the code
  • Configuration file

    server: port: 8201 spring: application: name: user-service eureka: client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://localhost:8001/eureka/ Copy the code
  • Define some interfaces to be called

    @RestController @RequestMapping("/user") public class UserController { private Logger LOGGER = LoggerFactory.getLogger( this .getClass()); @Autowired private UserService userService; @PostMapping("/create") public CommonResult create ( @RequestBody User user) { userService.create(user); return new CommonResult( "Operation successful" , 200 ); } @GetMapping("/{id}") public CommonResult<User> getUser ( @PathVariable Long id) { User user = userService.getUser(id); LOGGER.info( "Acquire user information according to id, the user name is: {}" ,user.getUsername()); return new CommonResult<>(user); } } Copy code

3.3.2 Call module (ribbon-service)

  • rely

    • Here is added spring-cloud-starter-netflix-ribbon to call other services
    < dependency > < groupId > org.springframework.boot </groupId > < artifactId > spring-boot-starter-web </artifactId > </dependency > < dependency > < groupId > org.springframework.cloud </groupId > < artifactId > spring-cloud-starter-netflix-eureka-client </artifactId > </dependency > < dependency > <groupId>org.springframework.cloud </the groupId > < the artifactId > Spring-Cloud-Starter-Netflix-Ribbon </the artifactId > </dependency > copy the code
  • Configuration file

    • service-url.user-service is the calling path of the user-service service on Eureka, which is convenient to retrieve the path through @value later
    server: port: 8301 spring: application: name: ribbon-service eureka: client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://localhost:8001/eureka/ service-url: Service-the User: HTTP://the User-Service copy the code
  • Add the RestTemplate component to the calling module through @LoadBalanced and give it the ability to load balance

    @Configuration public class RibbonConfig { @Bean @LoadBalanced public RestTemplate restTemplate () { return new RestTemplate(); } } Copy code
  • The calling module only adds the controller to call the service function of the user-service module (via restTemplate)

    @RestController @RequestMapping("/user") public class UserRibbonController { @Autowired private RestTemplate restTemplate; @Value("${service-url.user-service}") private String userServiceUrl; @GetMapping("/{id}") public CommonResult getUser ( @PathVariable Long id) { return restTemplate.getForObject(userServiceUrl + "/user/{1}" , CommonResult.class, id); } @GetMapping("/getByUsername") public CommonResult getByUsername ( @RequestParam String username) { return restTemplate.getForObject(userServiceUrl + "/user/getByUsername?username={1}" , CommonResult.class, username); } } Copy code

3.4 Ribbon common configuration

3.4.1 Global configuration

ribbon: ConnectTimeout: 1000 #Service request connection timeout time (milliseconds) ReadTimeout: 3000 #Service request processing timeout time (milliseconds) OkToRetryOnAllOperations: true #Enable retry mechanism for timeout requests MaxAutoRetriesNextServer: 1 #Switch the maximum number of retry instances MaxAutoRetries : 1 after example # handover maximum number of retries NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # modify the load balancing algorithm duplicated code

3.4.2 Specify the service for configuration

user-service: ribbon: ConnectTimeout: 1000 #Service request connection timeout time (milliseconds) ReadTimeout: 3000 #Service request processing timeout time (milliseconds) OkToRetryOnAllOperations: true #Enable retry mechanism for timeout requests MaxAutoRetriesNextServer: 1 #Switch to retry instance maximum number MaxAutoRetries: . 1 after the switching instance # maximum number of retries NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # modify the load balancing algorithm duplicated code

3.4.3 Ribbon load balancing strategy

  • com.netflix.loadbalancer.RandomRule: Randomly from the instances that provide the service
  • com.netflix.loadbalancer.RoundRobinRule: In a linear polling method, a counter is maintained, selected in order from the instances that provide services, the first is selected for the first time, the second is selected for the second, and so on. I'll start all over again after the last one
  • com.netflix.loadbalancer.RetryRule: Add a retry mechanism on the basis of RoundRobinRule, that is, within the specified retry time, the linear polling strategy is used repeatedly to select available instances
  • com.netflix.loadbalancer.WeightedResponseTimeRule: an extension of RoundRobinRule, the faster the response speed, the greater the weight of the instance selection, and the easier it is to be selected
  • com.netflix.loadbalancer.BestAvailableRule: select the instance with less concurrency
  • com.netflix.loadbalancer.AvailabilityFilteringRule: First filter out the failed instances, and then select the instances with less concurrency
  • com.netflix.loadbalancer.ZoneAwareLoadBalancer: Double filtering is adopted, and instances and faulty instances that are not in the same zone are filtered at the same time, and instances with less concurrency are selected

4 Hystrix (service fault tolerance protection)

4.1 Overview

4.1.1 Problems faced by distributed systems

  • Applications in a complex distributed architecture have dozens of dependencies, and each dependency will inevitably fail at some point

  • Service avalanche
    • effect
      • The service avalanche effect is a phenomenon in which the service caller is unavailable (result) due to the unavailability of the service provider (cause), and the unavailability is gradually enlarged
      • A is the service provider, B is the service caller of A, and C and D are the service callers of B. When the unavailability of A causes the unavailability of B, and the unavailability gradually enlarges C and D, the service avalanche is form

    • Cause of formation

    • preventive solution

4.1.2 Hystrix

  • Hystrix is an open source library used to handle the delay and fault tolerance of distributed systems. In distributed systems, many dependencies will inevitably fail to call, such as timeouts, exceptions, etc. Hystrix can guarantee that in the case of a dependency problem , Will not cause overall service failure, avoid cascading failures, and improve the resilience of distributed systems
  • The "circuit breaker" itself is a kind of switching device. When a service unit fails, the fault monitoring of the circuit breaker (similar to a blown fuse) returns an alternative response (FallBack) that meets expectations and can be handled to the caller. , Instead of waiting for a long time or throwing an exception that the caller cannot handle

4.2 Service fusing and downgrading

4.2.1 Create module to demonstrate hystrix function (hystrix-service)

  • rely

    < dependency > < groupId > org.springframework.cloud </groupId > < artifactId > spring-cloud-starter-netflix-eureka-client </artifactId > </dependency > < dependency > < groupId > org.springframework.cloud </groupId > < artifactId > spring-cloud-starter-netflix-hystrix </artifactId > </dependency > < dependency > groupId<> Org.springframework.boot </the groupId > < the artifactId > Spring-Boot-Starter-Web </the artifactId > </dependency > copy the code
  • Configuration file

    • service-url.user-service is also to obtain the service address of user-service
    server: port: 8401 spring: application: name: hystrix-service eureka: client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://localhost:8001/eureka/ service-url: Service-the User: HTTP://the User-Service copy the code
  • Turn on the circuit breaker function

    @SpringBootApplication @EnableDiscoveryClient @EnableCircuitBreaker public class HystrixServiceApplication { public static void main (String[] args) { SpringApplication.run(HystrixServiceApplication.class, args); } } Copy code
  • Create a controller to call the user-service service

    @RestController @RequestMapping("/user") public class UserHystrixController { @Autowired private UserService userService; @GetMapping("/testFallback/{id}") public CommonResult testFallback ( @PathVariable Long id) { return userService.getUser(id); } } Copy code
  • Actually call the user-service service at the service layer

    • restTemplate is injected into the IOC container after custom load balancing, so get it directly
    • userServiceUrl is the service address of the user-service predefined in the configuration file
    • restTemplate.getForObject calls the service path in user-service to get the result
    @Service public class UserService { private Logger LOGGER = LoggerFactory.getLogger( this .getClass()); @Autowired private RestTemplate restTemplate; @Value("${service-url.user-service}") private String userServiceUrl; @HystrixCommand(fallbackMethod = "getDefaultUser") public CommonResult getUser (Long id) { return restTemplate.getForObject(userServiceUrl + "/user/{1}" ,CommonResult.class,id); } public CommonResult getDefaultUser ( @PathVariable Long id) { User defaultUser = new User(- 1L , "defaultUser" , "123456" ); return new CommonResult<>(defaultUser); } } Copy code
  • result

    • The user-service module can be called through the hystrix-service module

    • When the user-service service is stopped, the default result of the circuit breaker can be obtained

4.2 Interpretation of Service Fuse

4.2.1 @HystrixCommand

  • The @HystrixCommand annotation appears in the UserService class. It can be seen that the getUser method calls user-service remotely through restTemplate, while the @HystrixCommand annotation is used to handle the default solution when the service fails

  • Common parameters

    • fallbackMethod: Specify the service degradation processing method
    • ignoreExceptions: Ignore some exceptions, no service degradation occurs
    • commandKey: command name, used to distinguish different commands
    • groupKey: group name, Hystrix will count command alarms and dashboard information according to different groups
    • threadPoolKey: thread pool name, used to divide thread pool

4.2.2 Hystrix request caching

4.2.3 Hystrix request to merge

4.3 Hystrix common configuration

4.3.1 Global configuration

hystrix: command: #Used to control the behavior of HystrixCommand default: execution: isolation: strategy: THREAD #Control the isolation strategy of HystrixCommand, THREAD->thread pool isolation strategy (default), SEMAPHORE->semaphore isolation strategy thread: timeoutInMilliseconds: 1000 #Configure the timeout time for HystrixCommand execution, and service degradation will occur if the execution exceeds this time. #Used to control whether to enable service degradation circuitBreaker: #Used to control the behavior of HystrixCircuitBreaker enabled: true #Used to control whether the circuit breaker tracks health status and fusing requests requestVolumeThreshold: 20 #Requests exceeding the number of requests will be rejected forceOpen: false #Forcibly open the circuit breaker and reject all requests forceClosed: false #Forcibly close the circuit breaker and receive all requests requestCache: enabled: interruptOnTimeout: to true # configure HystrixCommand execution timeout when you want to interrupt interruptOnCancel: to true # configure HystrixCommand execution is canceled when you want to interrupt timeout: Enabled: to true # Configure the execution of HystrixCommand whether to enable the timeout time semaphore: maxConcurrentRequests: 10 #When using the semaphore isolation strategy, it is used to control the size of the concurrent amount. Requests exceeding the concurrent amount will be rejected fallback: enabled: true to true # for controlling whether to turn on the cache request collapser: # for performing the behavior control HystrixCollapser default: maxRequestsInBatch: 100 # control The maximum number of requests for a merge request to be merged timerDelayinMilliseconds: 10 #Control how many milliseconds requests will be merged into one requestCache: enabled: true #Control whether the merge request is to be cached threadpool: #Used to control the behavior of the thread pool where HystrixCommand is executed default: coresize The: 10 # core thread pool threads maximumSize: 10 # maximum number of threads in the thread pool threads exceeds the number of requests will be rejected maxQueueSize: -1 # for Set the maximum queue size of the thread pool, -1 uses SynchronousQueue, and other positive numbers use LinkedBlockingQueue queueSizeRejectionThreshold: 5 #Used to set the rejection threshold of the thread pool queue, because LinkedBlockingQueue cannot dynamically change the size, you need to use this parameter to control the number of threads when using it. Copy code

4.3.2 Instance configuration

The instance configuration only needs to replace the default in the global configuration with the corresponding key.

Hystrix: Command: HystrixComandKey: # replace the default HystrixComrnandKey Execution: Isolation: Strategy: the THREAD collapser: HystrixCollapserKey: # replace the default HystrixCollapserKey maxRequestsInBatch: 100 ThreadPool: HystrixThreadPoolKey: # replace the default HystrixThreadPoolKey coresize The: 10 copy the code
  • Description of the relevant key in the configuration file
    • HystrixComandKey corresponds to the commandKey property in @HystrixCommand
    • HystrixCollapserKey corresponds to the collapserKey attribute in the @HystrixCollapser annotation
    • HystrixThreadPoolKey corresponds to the threadPoolKey property in @HystrixCommand

5 Hystrix Dashboard (circuit breaker execution monitoring)

5.1 Overview

  • Hystrix Dashboard is a dashboard component for viewing the execution of Hystrix instances in Spring Cloud. It supports viewing individual instances and viewing cluster instances
  • Hystrix provides Hystrix Dashboard to monitor the execution of the HystrixCommand method in real time. Hystrix Dashboard can effectively reflect the operation of each Hystrix instance and help quickly find problems in the system.

5.2 Circuit breaker execution monitoring

5.2.1 Create module execution monitoring (hystrix-dashboard)

  • rely

    < dependency > < groupId > org.springframework.cloud </groupId > < artifactId > spring-cloud-starter-netflix-eureka-client </artifactId > </dependency > < dependency > < groupId > org.springframework.cloud </groupId > < artifactId > spring-cloud-starter-netflix-hystrix-dashboard </artifactId > </dependency > <dependency > < The groupId > org.springframework.boot </the groupId > < the artifactId > Spring-Boot-Starter-Actuator </the artifactId > </dependency > copy the code
  • Configuration file

    Server: Port: 8501 the Spring: the Application: name: hystrix-Dashboard Eureka: Client: the Register-with-Eureka: to true FETCH-Registry: to true Service-url: defaultzone: HTTP://localhost: 8001/Eureka/ Copy the code
  • Turn on the monitoring function

    @SpringBootApplication @EnableDiscoveryClient @EnableHystrixDashboard public class HystrixDashboardApplication { public static void main (String[] args) { SpringApplication.run(HystrixDashboardApplication.class, args); } } Copy code
  • View monitoring information

    • Note: The service to be monitored must enable Actuator's hystrix.stream endpoint, which is the port 8401 configuration file to add:

      Management: Endpoints: Web: Exposure: the include: 'hystrix.stream' # monitors endpoints exposed hystrix duplicated code
  • Monitoring results

5.3 Hystrix cluster instance monitoring

  • Use Turbine to aggregate the monitoring information of the hystrix-service service, and then the hystrix-dashboard service can obtain the aggregated monitoring information from Turbine

5.3.1 Create a module to aggregate the monitoring information of hystrix-service (turbine-service)

6 OpenFeign (declarative service call based on Ribbon and Hystrix)

6.1 Overview

  • Feign is a declarative WebService client
  • When Ribbon+RestTemplate was used before, a set of templated invocation methods was formed by using RestTemplate to encapsulate http requests. In actual development, one interface is often called more often, and Feign has made further encapsulation on this basis to help Define and implement the definition of dependent service interface
  • Feign integrates Ribbon to achieve client load balancing through polling

6.2 Feign test

6.2.1 Create a module to demonstrate Feign service invocation function (feign-service)

  • rely

    < dependency > < groupId > org.springframework.cloud </groupId > < artifactId > spring-cloud-starter-netflix-eureka-client </artifactId > </dependency > < dependency > < groupId > org.springframework.cloud </groupId > < artifactId > spring-cloud-starter-openfeign </artifactId > </dependency > < dependency > <the groupId > org.springframework.boot </the groupId > < the artifactId > Spring-Boot-Starter-Web </the artifactId > </dependency > copy the code
  • Configuration file

    Server: Port: 8701 the Spring: the Application: name: Feign-Service Eureka: Client: the Register-with-Eureka: to true FETCH-Registry: to true Service-url: defaultzone: HTTP://localhost: 8001/Eureka/ Copy the code
  • Enable Feign client function

    @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class FeignServiceApplication { public static void main (String[] args) { SpringApplication.run(FeignServiceApplication.class, args); } } Copy code
  • Add UserService interface to realize binding to user-service service Controller interface

    • A Feign client is implemented through the @FeignClient annotation, where the value is user-service, which means that it is the client to call the interface of the user-service service

    • The method of the UserService interface is essentially to delete the method content of the method corresponding to the controller in the user-service service, and only keep the interface

      @FeignClient(value = "user-service") public interface UserService { @PostMapping("/user/create") CommonResult create ( @RequestBody User user) ; @GetMapping("/user/{id}") CommonResult<User> getUser ( @PathVariable Long id) ; @GetMapping("/user/getByUsername") CommonResult<User> getByUsername ( @RequestParam String username) ; @PostMapping("/user/update") CommonResult update ( @RequestBody User user) ; @PostMapping("/user/delete/{id}") CommonResult delete ( @PathVariable Long id) ; } Copy code
  • Add controller to call methods in UserService (omitted)

  • User-service re-transforms a configuration file, and specifies Active Profile on the startup configuration to start the user-service of another port to detect Feign s load balancing capabilities

  • Test results (the user-service services running on 8201 and 8202 are called alternately)

6.2.2 Test service degradation in Feign

  • Add the implementation class of the UserService interface as a service downgrade class

    public class UserServiceImpl implements UserService { @Override public CommonResult create (User user) { User defaultUser = new User(- 1L , "defaultUser" , "123456" ); return new CommonResult<>(defaultUser); } @Override public CommonResult<User> getUser (Long id) { User defaultUser = new User(- 1L , "defaultUser" , "123456" ); return new CommonResult<>(defaultUser); } @Override public CommonResult<User> getByUsername (String username) { User defaultUser = new User(- 1L , "defaultUser" , "123456" ); return new CommonResult<>(defaultUser); } @Override public CommonResult update (User user) { return new CommonResult( "The call failed, the service was downgraded" , 500 ); } @Override public CommonResult delete (Long id) { return new CommonResult( "The call failed, the service was downgraded" , 500 ); } } Copy code
  • Specify the service degradation class as UserServiceImpl

  • Turn on the Hystrix function in the configuration file

6.2.3 Feign log printing function

  • Feign provides a log printing function, you can adjust the log level through configuration, so as to understand the details of the Http request in Feign

  • Log level

    • NONE: By default, no logs are displayed
    • BASIC: Only record the request method, URL, response status code and execution time
    • HEADERS: In addition to the information defined in BASIC, there are also request and response header information
    • FULL: In addition to the information defined in HEADERS, there are also the body and metadata of the request and response
  • Configure Logger.Level (Logger comes from feign.Logger)

    @Configuration public class FeignConfig { @Bean public Logger. Level feignLoggerLevel () { return Logger.Level.FULL; } } Copy code
  • Feign client with logging enabled in the configuration file

    • Configure the log level of UserService to debug

      logging: Level: org.jiang.service.UserService: Debug copy the code
  • View log

6.3 Feign common configuration

6.3.1 Feign's own configuration

feign: hystrix: enabled: true #Turn on Hystrix compression in Feign : request: enabled: false #Whether to perform GZIP compression on the request mime-types: text/xml,application/xml,application/json #Specify the compressed request data type min -request-size: 2048 #Requests exceeding this size will be compressed response: Enabled: to false if the response # GZIP compression on the logging: level: # change the log level com.macro.cloud.service.UserService: Debug copy the code

6.3.2 Ribbon configuration in Feign

  • Configuring Ribbon in Feign can directly use Ribbon's configuration

6.3.3 Hystrix configuration in Feign

  • Configuring Hystrix in Feign can directly use the configuration of Hystrix

7 Config (external centralized configuration management)

7.1 Overview

7.1.1 Configuration problems faced by distributed systems

  • Microservices means to split the business in a single application into sub-services. The granularity of each service is relatively small. A large amount of configuration information will appear in the system for operation, so the common parts are extracted into a set of centralized services. Indispensable, dynamic configuration management facilities

7.1.2 Spring Cloud Config

  • Spring Cloud Config provides centralized external configuration support for microservices, and the configuration server provides a centralized external configuration for different microservice applications

  • Spring Cloud Config is divided into two parts: server and client

    • The server is called a distributed configuration center. It is an independent application that can obtain configuration information from the configuration warehouse and provide it to the client.
    • The client can obtain configuration information through the configuration center, and load the configuration at startup
    • The configuration center of Spring Cloud Config uses Git to store configuration information by default, so it naturally supports version management of configuration information, and you can use the Git client to easily manage and access configuration information

7.2 Set up a configuration center to achieve central configuration

7.2.1 Remote warehouse preparation configuration information

  • Spring Cloud Config needs a Git warehouse to store configuration information, so add the configuration file in the Git warehouse in advance

  • git warehouse address: gitee.com/macrozheng/...

  • Configure the warehouse directory structure

    • Provides different branches, different branches are configured with different environments, production, development, and testing

7.2.2 Create a configuration center module to demonstrate the Config configuration center function (config-server)

  • rely

    • The spring-cloud-config-server dependency is added here to serve as the configuration center
    < dependency > < groupId > org.springframework.cloud </groupId > < artifactId > spring-cloud-config-server </artifactId > </dependency > < dependency > < groupId > org.springframework.cloud </groupId > < artifactId > Spring-Cloud-Starter-Netflix-Eureka-Client </the artifactId > </dependency > copy the code
  • Configuration file

    • Added information for spring.cloud.config.server to configure git warehouse
    server: port: 8901 spring: application: name: config-server cloud: config: server: git: #Configure the Git warehouse uri for storing configuration information : https://gitee.com/macrozheng/springcloud-config.git username: macro password: 123456 clone-ON-start: to true # open when you start to get the configuration directly from the git Eureka: Client: Service-url: defaultzone: HTTP://localhost: 8001/Eureka/ copy the code
  • Enable configuration center function

    @SpringBootApplication @EnableDiscoveryClient @EnableConfigServer public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } } Copy code
  • Obtain configuration information through config-server

    • Access format for obtaining configuration file information

      Configuration information # /label {}/{file application} - {Profile} # acquires profile information /{label}/{application}-{profile}.yml duplicated code
    • Placeholder related explanation

      • application: represents the application name, the default is spring.application.name in the configuration file, if spring.cloud.config.name is configured, it is the name
      • label: represents the branch name, corresponding to spring.cloud.config.label in the configuration file
      • profile: represents the environment name, corresponding to spring.cloud.config.profile in the configuration file
    • Get configuration information

      • Read configuration information address: http://localhost:8901/master/config-dev

      • The reason for this request address is that the default format of the configuration file in the git repository is {application}-{profile}.yml, that is, config represents application

  • Obtain configuration file information through config-server

7.3 Build a client to obtain configuration information of the configuration center

7.3.1 Create a module for access (config-client)

  • rely

    • Compared with the configuration center, the spring-boot-starter-web module has been added, indicating that network requests are to be made
    • Here is spring-cloud-starter-config, and the configuration center uses spring-cloud-config-server
    < Dependency > < the groupId > org.springframework.cloud </the groupId > < the artifactId > Spring-Starter-config-Cloud </the artifactId > </dependency > < dependency > > < groupId > org.springframework.cloud </groupId > < artifactId > spring-cloud-starter-netflix-eureka-client </artifactId > </dependency > < dependency > groupId< Org.springframework.boot </the groupId > < the artifactId > Spring-Boot-Starter-Web </the artifactId > </dependency > copy the code
  • Configuration file bootstrap.yml

    • bootstrap.yml

      • Spring Cloud will create a Bootstrap Context as the parent context of the Application Context of the Spring application
      • Bootstrap Context is responsible for loading configuration properties from external sources and parsing the configuration, and shares an externally obtained environment with Application Context
      • Bootstrap properties have high priority and will not be overridden by local configuration by default. Bootstrap Context and Application Context have different conventions, so bootstrap.yml is added to separate from Application Context configuration
      • Bootstrap.yml is loaded prior to application.yml
    • Configuration file content

      • There is no spring.cloud.config.server, but spring.cloud.config, because this is the client
      • Get the address of the configuration center, the name of the configuration file, and the branch name respectively, which correspond to the application, label, and profile
      server: port: 9001 spring: application: name: config-client cloud: config: #Config client configuration profile: dev #Enable configuration suffix name label: dev #Branch name uri: http://localhost:8901 #Configuration center address name: config #Configuration file name eureka: client: service-url: defaultZone: http://localhost:8001/eureka/ Copy code
  • Create a controller test to obtain configuration file information

    • Why @Value("${config.info}")

    • The configuration file information read from the configuration center is like this, so you can use config.info to read

    @RestController public class ConfigClientController { @Value("${config.info}") private String configInfo; @GetMapping("/configInfo") public String getConfigInfo () { return configInfo; } } Copy code
  • test

  • Get the configuration in the subdirectory

    • Not only can the configuration of each project be stored in a different Git repository, but also the configuration of multiple projects can be stored in a Git repository. At this time, the configuration of searching for configuration information in a subdirectory will be used.

    • The config folder represents the configuration file of the config application under the dev branch

    • method of obtaining

      • Add configuration to the configuration file of config-server to search for the location of the subdirectory. Use the application placeholder to indicate that for different applications, we search for the configuration from the subdirectory corresponding to the application name, such as the configuration in the config subdirectory Corresponding to config application

    • Get results

      • It can be found that the configuration file information in the config subdirectory is obtained

7.3.2 Configuration refresh

  • When the configuration information in the Git repository is changed, we can refresh the client configuration information through the refresh endpoint of SpringBoot Actuator
Improve config-client
  • Add dependency

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> Copy code
  • Modify the configuration file to add the actuator configuration to enable the refresh endpoint

    management: endpoints: Web: Exposure: the include: 'Refresh' duplicated code
  • Add @RefreshScope annotation on the controller class to refresh the configuration

    @RestController @RefreshScope public class ConfigClientController { @Value("${config.info}") private String configInfo; @GetMapping("/configInfo") public String getConfigInfo () { return configInfo; } } Copy code
  • Send a post request and call the refresh endpoint to refresh the configuration (monitor version changes)

7.4 Add Security Verification in Configuration Center

7.4.1 Add modules to integrate Spring Security (config-security-server)

  • rely

    <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId > Boot-Spring-Security-Starter </the artifactId> </dependency> copy the code
  • Configuration file

    • Added configuration for security account
    server: port: 8905 spring: application: name: config-security-server cloud: config: server: git: uri: https://gitee.com/macrozheng/springcloud-config.git username: macro password: 123456 clone-on -start: to true get turned on when # started directly from the git configuration Security: # configure the user name and password for the user: name: Macro password: 123456 copy the code

7.4.2 Modify config-client to match the configuration center with added security authentication

  • Add a bootstrap-security.yml configuration file to match the configuration center configured with a user name and password, and use bootstrap-security.yml to start the config-client service

    server: port: 9002 spring: the Application: name: config-Client Cloud: config: Profile: dev # Enable configuration suffix name label: dev # Branch Name uri: HTTP://localhost: 8905 # Configure Center Address name: config # Configure File name username: macro password: 123456 eureka: client: service-url: defaultZone: http://localhost:8001/eureka/ Management: Endpoints: Web: Exposure: the include: 'Refresh' duplicated code

7.5 config-sever cluster

  • In the microservice architecture, all services obtain configuration from the configuration center. Once the configuration center goes down, serious problems will occur; therefore, it is necessary to build a configuration center cluster

7.5.1 Build a configuration center cluster

  • Start two config-servers running on ports 8902 and 8903 respectively

  • Add the configuration file bootstrap-cluster.yml of config-client, mainly to add the configuration of obtaining the configuration center address from the registration center and remove the configuration of the configuration center uri

    • bootstrap-cluster.yml

      spring: cloud: config: profile: dev #Enable environment name label: dev #Enable #Branch name name: config #Configuration file name discovery: enabled: true service-id: config-server eureka: client: service-url: defaultZone: http://localhost:8001/eureka/ Copy code
  • Start the config-client service with bootstrap-cluster.yml, and the registration center displays the information

8 Bus (message bus)

8.1 Overview

  • Spring Cloud Bus uses a lightweight message broker to connect various services in the microservice architecture, which can be used to broadcast state changes (such as configuration center configuration changes) or other management instructions
  • Use a message broker to build a topic, and then connect all services in the microservice architecture to this topic. When we send a message to the topic, all services that subscribe to the topic will receive the message and consume it
  • Spring Cloud Bus can be used with Spring Cloud Config to realize dynamic refresh of configuration

8.2 Install RabbitMQ

8.3 Add dynamic refresh configuration function

  • Using Spring Cloud Bus to dynamically refresh the configuration needs to be used in conjunction with Spring Cloud Config. This function is demonstrated through the config-server and config-client modules

8.3.1 Modification of config-server module

  • Add dependency

    < dependency > < groupId > org.springframework.cloud </groupId > < artifactId > spring-cloud-starter-bus-amqp </artifactId > </dependency > < dependency > < groupId > org.springframework.boot </groupId > < the artifactId > Spring-Boot-Starter-Actuator </the artifactId > </dependency > copy the code
  • Configuration file modification

    • Add the configuration file application-amqp.yml, mainly to add the configuration of RabbitMQ and expose the Actuator endpoint of the refresh configuration

      server: port: 8904 spring: application: name: config-server cloud: config: server: git: uri: https://gitee.com/macrozheng/springcloud-config.git username: macro password: 123456 clone-on-start : true # Get the configuration directly from git when you turn on rabbitmq: #rabbitmq related configuration host: localhost port: 5672 username: guest password: guest eureka: client: service-url: defaultZone: http://localhost:8001/eureka/ management : endpoints: #Exposing the endpoint of bus refresh configuration web: Exposure: the include: 'bus-Refresh' duplicated code

8.3.2 Modification of config-client module

  • Add dependency

    < dependency > < groupId > org.springframework.cloud </groupId > < artifactId > Spring-Cloud-Starter-Bus-AMQP </the artifactId > </dependency > copy the code
  • Modify the configuration file

    • Add configuration files bootstrap-amqp1.yml and bootstrap-amqp2.yml to start two different config-clients, the two configuration files only have different port numbers

      server: port: 9004 spring: application: name: config-client cloud: config: profile: dev #Enable environment name label: dev #Branch name name: config #Configuration file name discovery: enabled: true service-id: config-server rabbitmq: #rabbitmq related configuration host: localhost port: 5672 username: guest password: guest eureka: client: service-url: defaultZone: http://localhost:8001/eureka/ management: endpoints: web: exposure: include: 'Refresh' duplicated code

8.3.3 Dynamic refresh configuration demonstration

  • Start related services first, start eureka-server, start config-server with application-amqp.yml as configuration, start config-client with bootstrap-amqp1.yml as configuration, and start a config-client with bootstrap-amqp2.yml as configuration , The registry will display after startup

  • After starting all services, log in to the RabbitMQ console and you can find that Spring Cloud Bus has created a switch called springCloudBus and three queues starting with springCloudBus.anonymous

8.4 Cooperate with WebHooks to realize automatic refresh service configuration

  • WebHooks is equivalent to a hook function. By configuring this hook function to be triggered when the code is pushed to the Git repository, the service configuration will be automatically refreshed when the code is pushed to the configuration repository

9 Sleuth (distributed request link tracking)

9.1 Overview

9.1.1 Problems encountered

  • In the microservice framework, a request initiated by a client will be called by many different service nodes in the back-end system to coordinately produce the final request result. Each front-end request will form a complex distributed service call link , High latency and errors in any link in the link will cause the final failure of the entire request

9.1.2 Solution

  • Spring Cloud Sleuth is a tool for tracking calls between services in a distributed system. It can visually show the call process of a request

  • Provide tracking solutions in distributed systems and support zipkin compatible

  • SpringCloud has no need to build Zipkin server by itself since F version, just call the jar package.

9.2 Service add request link tracking function

  • Demonstrate this function through the service call between user-service and ribbon-service. When the interface of ribbon-service will be called, ribbon-service will call the interface provided by user-service through RestTemplate

9.2.1 Download and build zipkin-server

  • Overview of zipkin-server

    • Zipkin is an open source distributed tracking system. Each service reports timing data to Zipkin, and Zipkin will generate a dependency graph through Zipkin UI based on the calling relationship.

    • Zipkin provides pluggable data storage methods: In-Memory, MySql, Cassandra, and Elasticsearch. In-Memory can be used for storage in the development environment for convenience. Elasticsearch is recommended for large amounts of production data.

    • Represents a request link, a link is uniquely identified by Trace Id, Span identifies the request information initiated, and each Span is associated with the parent id

      • Trace: Span set similar to a tree structure, representing a call link, with a unique identifier
      • span: Indicates the source of the calling link. In popular understanding, span is a request for information.

  • Build the zipkin server

    • Download the zipkin server jar package: dl.bintray.com/openzipkin/...

    • Start the server, the default INFO level can be set without logging

      • Command: java -jar zipkin-server-2.10.4-exec.jar --logging.level.zipkin2=INFO
    • Successfully started

    • Access server

9.2.1 user-service and ribbon-service add support for requesting link tracking function

  • Add dependency on user-service and ribbon-service

    < Dependency > < the groupId > org.springframework.cloud </the groupId > < the artifactId > Spring-Cloud-Starter-Zipkin </the artifactId > </dependency > copy the code
  • User-service and ribbon-service modify configuration files

    • Added the request address of zipkin and the probability of sleuth sampling collection
    server: port: 8201 spring: application: name: user-service zipkin: base-url: http://localhost:9411 sleuth: sampler: probability: 0.1 #Set the sampling probability of Sleuth Eureka: Client: the Register-with-Eureka: to true FETCH-Registry: to true Service-url: defaultzone: HTTP://localhost: 8001/Eureka/ Copy the code
  • Multiple calls (Sleuth is sampling collection) ribbon-service interface http://localhost:8301/user/1 , after calling, check the link tracking information of Zipkin request

9.3 Integrate Elasticsearch to store tracking information

9.3.1 Elasticsearch installation and configuration

  • Download the zip installation package and unzip

  • Run elasticsearch.bat in the bin directory to start Elasticsearch

  • Start interface

  • Restart zipkin and specify startup parameters

    • # STORAGE_TYPE: indicates the type of storage ES_HOSTS: ES access address indicates the Java -jar Zipkin-Server-2.12.9-exec.jar --STORAGE_TYPE = elasticsearch --ES_HOSTS = localhost: 9200 copy the code
  • Restart the user-service and ribbon-service services (only restart the storage to take effect)

  • zipkin startup parameter reference: github.com/openzipkin/...

9.3.2 Kibana, a visualization tool with Elasticsearch


The personal official account is currently under preliminary construction. If you like, you can follow my official account, thank you!