Summary of SpringCloud study notes (3)

Git code address: https://gitee.com/it-sherlock/java-project-template .

1. Zookeeper payment service registration (service provider registration)


insert image description here

zookeeper official download:


Step 1: Create a new business logic project to facilitate testing and import the corresponding zookeeper dependencies:

<!--SpringBoot整合zookeeper客户端-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>

Step 2: Configure application.yml:

server:
  port: 8004

# 服务别名--注册zookeeper到注册中心名称
spring:
  application:
    name: cloud-provider-payment
  cloud:
  	# 注册到zookeeper
    zookeeper:
      connect-string: 150.158.199.52:2181

Step 3: Add the SpringBoot startup class:

package com.itholmes.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
/**
 * 注解@EnableDiscoveryClient:
 *      用于像使用consul或者zookeeper作为注册中心时注册服务。
 */
@EnableDiscoveryClient
public class PaymentMain8004 {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(PaymentMain8004.class,args);
    }
}

Step 4: Enter the bin directory of zookeeper and start zookeeper through ./zkServer.sh start:

  • ./zkServer.sh start start zookeeper.
  • ./zkCli.sh to enter the zookeeper client.
  • Before startup 一定要看看conf目录下面的zoo.cfg文件, there is usually a zoo.sample.cfg, which needs to be copied to a zoo.cfg file to start zookeeper normally.

insert image description here

Notice:
insert image description here


Step 5: Start the business logic project.

  • May encounter jar conflicts! If the dependent jar package of zookeeper is inconsistent with the version of zookeeper installed on the server, there will be a problem of jar package conflict!
    insert image description here
    How to solve the conflict between the zookeeper version jar package and the server version?

  • The zookeeper 3.5.3 version that comes with the jar package can be excluded through exclusions, and dependencies of other versions can be added.

<!--SpringBoot整合zookeeper客户端-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
    <exclusions>
    	<!--排除自身版本的zookeeper-->
        <exclusion>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!--添加新版本的zookeeper。-->
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.9</version>
</dependency>

Step 6: Start the project and check whether the zookeeper service is registered.
insert image description here
insert image description here

2. Temporary node and persistent node of zookeeper


Zookeeper can be divided into temporary nodes and persistent nodes.

It can also be subdivided into temporary nodes without serial numbers, temporary nodes with serial numbers, persistent nodes without serial numbers, and persistent nodes with serial numbers.

Zookeeper on the current server, when we shut down the business logic system, zookeeper will immediately delete the service registration information if it cannot receive the heartbeat within a certain period of time, indicating that the zookeeper server is a temporary node.

3. Service consumer registration of zookeeper


Register the consumer system with zookeeper and get provider information from zookeeper.


Step 1: Create a service consumer for the same project, configure the pom, and create a springboot startup class.

package com.itholmes.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
// 不要忘记添加!!!
@EnableDiscoveryClient
public class OrderZKMain {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(OrderZKMain.class,args);
    }
}


Step 2: Register the service consumer with zookeeper.

server:
  port: 80

# 服务别名--注册zookeeper到注册中心名称
spring:
  application:
    name: cloud-consumer-order
  cloud:
  # 注册到zookeeper
    zookeeper:
      connect-string: 150.158.199.52:2181


Step 3: Add the RestTemplate object to the container, and don't forget to add the @LoadBalanced annotation:

package com.itholmes.springcloud.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ApplicationContextConfig {
    
    
    @Bean
    //添加@LoadBalanced负载均衡注解
    @LoadBalanced
    public RestTemplate getRestTemplate(){
    
    
        return new RestTemplate();
    }
}


Step 4: Add a controller layer, and use RestTemplate to access it through the name of the microservice registered by the service:

package com.itholmes.springcloud.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;

@RestController
@Slf4j
public class OrderZKController {
    
    

    public static final String INVOKE_URL = "http://cloud-provider-payment";

    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/consumer/payment/zk")
    public String paymentInfo(){
    
    
        String result = restTemplate.getForObject(INVOKE_URL + "/payment/zk", String.class);
        return result;
    }

}

Here I still encounter the problem that the domain name cannot contain underscores!
insert image description here

So in the end I was convinced and decided to change the name of the computer host. . .
insert image description here

4. Introduction to Consul


Consul is an open source distributed service discovery and configuration management system developed by HahsiCorp in go language.

Advantages of Consul:
insert image description here

Download address: https://learn.hashicorp.com/tutorials/consul/get-started-install

5. Install and run Consul


Go to the official download package of Consul and transfer it to the server:

  • For zip files, use the unzip command to unzip them.

Use consul --version to view the consul version:
insert image description here

Start consul in development mode via consul agent -dev:

  • Note: If it is cloud access, you also need to add the -client 0.0.0.0 parameter.
consul agent -dev # 该命令启动只能允许本机访问
consul agent -dev -client 0.0.0.0  # 加上-client 0.0.0.0就可以其他机器进行访问了

insert image description here


In this way, we can access the web page of consul by visiting the page:
insert image description here

6. Consul's service provider is registered into consul


Also create a service provider project, change the pom import dependencies, add configuration files and startup classes.

The first step: corresponding to the important dependencies of consul:

<!--SpringCloud consul-server的客户端-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Step 2: SpringBoot's integration of consul and application.yml.

server:
  port: 8006

spring:
  application:
    # 微服务名称
    name: consul-provider-payment
  # consul注册中心地址
  cloud:
    consul:
      host: 150.158.199.52
      port: 8500
      discovery:
        # hostname: 127.0.0.1
        service-name: ${
    
    spring.application.name}
        # healthbeat.enable 为 true 就是打开心跳机制,重新启动服务就不会再出现前面的问题了。
        heartbeat:
          enabled: true

Step 3: Add the main startup class.

package com.itholmes.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain8006 {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(PaymentMain8006.class,args);
    }
}

Step 4: You can view it on the consul web page.
insert image description here
(Note that the red cross above will appear if heartbeat detection is not turned on.)

7. Consul's service consumers are registered in Consul


Also create a service provider project, change the pom import dependencies, add configuration files and startup classes.

application.yml configuration:

server:
  port: 80

spring:
  application:
    # 微服务名称
    name: consul-consumer-order
  # consul注册中心地址
  cloud:
    consul:
      host: 150.158.199.52
      port: 8500
      discovery:
        # hostname: 127.0.0.1
        service-name: ${
    
    spring.application.name}
        # healthbeat.enable 为 true 就是打开心跳机制,重新启动服务就不会再出现前面的问题了。
        heartbeat:
          enabled: true

Don't forget to add the @LoadBalanced annotation to the configuration class RestTemplate:

package com.itholmes.springcloud.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ApplicationContextConfig {
    
    
    @Bean
    //添加@LoadBalanced负载均衡注解
    @LoadBalanced
    public RestTemplate getRestTemplate(){
    
    
        return new RestTemplate();
    }
}

Startup configuration class:

package com.itholmes.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient//该注解用于向使用consul或者zookeeper作为注册中心注册服务
public class OrderConsulMain80 {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(OrderConsulMain80.class,args);
    }
}

8. Similarities and differences of the three registries


insert image description here

CAP concept:
insert image description here
Since it is a distributed microservice, P is always guaranteed, either CP or AP.

  • The eureka branch is AP.
  • The zoo keeper and consul branches are CP.

9. Introduction of Ribbon


SpringCloud Ribbon is a set of client load balancing tools based on Netflix Ribbon.

The role of Ribbon: The main function is to provide the client's software load balancing algorithm and service invocation.

Ribbon client components provide a series of sophisticated items such as connection timeout, retry and so on. Simply put, it is to list all the machines behind the Load Balancer (LB for short, load balancing) in the configuration file, and Ribbon will automatically help you connect to these machines based on certain rules (such as simple polling, random connection, etc.).

Ribbon's github address: https://github.com/Netflix/ribbon

ribbon is currently maintained, but still used in many projects!


Common load balancing software includes: Nginx, LVS, hardware F5, etc.

There are two types of LB load balancing: centralized LB and in-process LB.

  • Nginx is server load balancing and belongs to a centralized LB.
  • Ribbon is a local load balancer and belongs to the process LB.
    insert image description here

So Ribbon is essentially a RestTemplate + load balancing call.

10. Ribbon's load balancing and Rest calls

10.1 Introduction of Ribbon Environment


Ribbon is a client component of soft load balancing.

The following figure is an architecture diagram of a combination of Ribbon and Eureka Server:
insert image description here

Ribbon has a variety of strategies: such as round robin, random and weighted according to the corresponding time.


Normally, we need to import:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>

But the new version of spring-cloud-starter-netflix-eureka-client has integrated ribbon! Therefore, when we use eureka, we have the effect of load balancing.
insert image description here

10.2 RestTemplate usage


RestTemplate mainly has two kinds of objects and entities:

  • The object returned is the object of data conversion in the response body, which is just like json.
  • The entity returned object is the ResponseEntity object, which contains some important information of the response, response headers, response status codes, response bodies, and so on. (A project I wrote recently happened to use the configuration response header to pass the token).
    insert image description here

11. Ribbon's default load balancing strategy


Several default load balancing strategies that come with ribbon:
insert image description here


Ribbon's core component iRule interface:

  • The above defaults are implemented in the implementation class that implements the iRule interface.
    insert image description here
    insert image description here
    insert image description here

12. Ribbon load balancing rule replacement


Before configuration, the official document clearly warns that custom configuration classes for configuring Ribbon cannot be placed under the current package and subpackages scanned by @ComponentScan! !
insert image description here


Set custom configuration class:

  • It is still important to note that this class cannot be set under the current package and sub-packages scanned by @ComponentScan! !
package com.itholmes.myrule;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

//还是要注意这个类不能设置在@ComponentScan所扫描当前包下以及子包下!!
@Configuration
public class MySelfRule {
    
    

    //注入IRule接口对应的一些实现类
    @Bean
    public IRule myRule(){
    
    
        //随机规则
        return new RandomRule();
    }

}

SpringBoot startup class:

  • You need to add the @RibbonClient annotation to specify the microservice name and configuration class.
package com.itholmes.springcloud;

import com.itholmes.myrule.MySelfRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;

@SpringBootApplication
@EnableEurekaClient
//在这指定好,这里的name是要访问那个微服务的名称;configuration来指定负载均衡的规则的配置类。
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
public class OrderMain80 {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(OrderMain80.class,args);
    }
}

13. Principle of Ribbon's default load balancing polling algorithm


Load balancing algorithm:

  • The number of requests of the rest interface for the first time % of the total number of server clusters = the index of the actual calling server location.
  • The rest interface count starts from 1 after each service restart.
    insert image description here

A spinlock is used:

What is a spin lock?

  • Spinlock means that when a thread tries to acquire a lock, if the lock is already occupied by other threads, it keeps looping to check whether the lock is released, instead of entering the thread suspend or sleep state.

insert image description here

14. Handwritten Ribbon polling algorithm


Define a LoadBalancer interface:

package com.itholmes.springcloud.lb;

import org.springframework.cloud.client.ServiceInstance;
import java.util.List;

public interface LoadBalancer {
    
    
    ServiceInstance instances(List<ServiceInstance> serviceInstances);
}

MyLB class, set the polling algorithm:

package com.itholmes.springcloud.lb;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class MyLB implements LoadBalancer{
    
    

    /**
     *  AtomicInteger类是系统底层保护的int类型,通过提供执行方法的控制进行值的原子操作。
     *  AtomicInteger它不能当作Integer来使用
     *
     */
    private AtomicInteger atomicInteger = new AtomicInteger(0);

    public final int getAndIncrement(){
    
    
        int current;
        int next;
        do {
    
    
            current = this.atomicInteger.get();
            //2147483647是integer的最大值。
            next = current >= 2147483647 ? 0 : current + 1;

        /**
         * java.util.concurrent.atomic.AtomicInteger.compareAndSet()是Java中的一种内置方法,
         * 如果当前值等于参数给定的期望值,则将值设置为参数中的传递值。该函数返回一个布尔值,该布尔值使我们了解更新是否完成。
         */
        }while (!this.atomicInteger.compareAndSet(current,next));
        System.out.println("*****第几次访问次数,next:"+next);
        return next;
    }

    @Override
    public ServiceInstance instances(List<ServiceInstance> serviceInstances) {
    
    
        //轮询算法
        int index = getAndIncrement() % serviceInstances.size();
        return serviceInstances.get(index);
    }
}

Controller layer verification:

@Resource
RestTemplate restTemplate;

@Resource
private DiscoveryClient discoveryClient;

@Resource
private LoadBalancer loadBalancer;

@GetMapping("/consumer/payment/lb")
public String getPaymentLB(){
    
    
    List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
    if (instances == null || instances.size()<=0){
    
    
        return null;
    }
    ServiceInstance instance = loadBalancer.instances(instances);
    URI uri = instance.getUri();
    return restTemplate.getForObject(uri+"/payment/lb",String.class);
}

Guess you like

Origin blog.csdn.net/IT_Holmes/article/details/125370800