Ribbon
An overview,
Spring Cloud Ribbon is a set of client load balancing tools based on the Netflix Ribbon.
Simply put, the Ribbon is an open source project released by Netflix. Its main function is to provide software load balancing algorithms and service invocation on the client side. The Ribbon client component provides a wide range of configuration options such as connection timeout and retry. Simply put, the Ribbon lists all the machines following the Load Balancer (LB) in the configuration file. The Ribbon automatically helps you connect them based on certain rules (simple polling, random connections, etc.). It’s easy to use the Ribbon to implement custom load balancing algorithms.
Official document: github.com/Netflix/rib…
LB Load balancing (LB) is a Load balancing system that distributes user requests to multiple services to achieve high availability (HA). Common Load balancing systems include software Nginx, LVS, and hardware F5.
Ribbon Local LB clients (in-process LB) vs. Nginx Server LB Differences (centralized LB) : Nginx is a SERVER LB. All client requests are forwarded to Nginx. That is, load balancing is implemented on the server side.
The Ribbon provides local load balancing. When a microservice interface is invoked, the Ribbon cache the list of registered services from the registry to the JVM. In this way, RPC remote service invocation technology is implemented locally.
Ribbon= Load balancing +RestTemplate calls
Ribbon Load balancing demo
1. Architecture description
The Ribbon works in two steps. The first step is to select EurekaServer. The first step is to select servers that have less load in the same area.
The second step is to select an address from the service registration list fetched from the server according to the policy specified by the user. The Ribbon provides a variety of strategies: such as polling, random, and weighting based on response time.
Conclusion: The Ribbon is a soft load-balancing client component that can be used with other clients that require it. Eureka is just one example.
2, POM
The Spring-cloud-starter – Netflix-Eureka-client comes with the Spring-cloud-starter -ribbon reference.
3. Use the RestTemplate
(1) official website
Docs. Spring. IO/spring – fram…
(2)getForObject method /getForEntity method
The returned object is the object converted from the data in the response body, which can be basically understood as Json.
The returned object is the ResponseEntity object, which contains important information about the response, such as the response header, the response status code, and the response body.
@GetMapping("/consumer/payment/getForEntity/{id}")
public CommonResult<Payment> getPayment2(@PathVariable("id") Long id){
ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
if(entity.getStatusCode().is2xxSuccessful()){
return entity.getBody();
}else{
return new CommonResult<>(444."Operation failed"); }}Copy the code
(3)postForObject/postForEntity
@GetMapping("/consumer/payment/create")
public CommonResult<Payment> create(Payment payment){
return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class);
//return restTemplate.postForEntity(PAYMENT_URL+"/payment/create",payment,CommonResult.class).getBody();
}
Copy the code
IRule, the core component of the Ribbon
1, IRule
Select a service to access from the list of services based on a particular algorithm:
Com.net flix. Loadbalancer. RoundRobinRule: polling
Com.net flix. Loadbalancer. RandomRule: random
Com.net flix. Loadbalancer. RetryRule: according to the first RoundRobinRule strategies for service, if failed to get the service within a specified time will retry, access to services available
WeightedResponseTimeRule: an extension of RoundRobinRule. The more responsive the instance is, the more likely it is to be selected
BestAvailableRule: Filters out the service that is in breaker trip state due to multiple access failures, and then selects the service with the least concurrency
AvailabilityFilteringRule: to filter out the first example, choose the instance of concurrent smaller again
ZoneAvoidanceRule: Default rule that selects a server based on compound judgments about performance and server availability in the zone where the server is located
2, how to replace
(1) to modify the cloud – consumer – order80
(2) Pay attention to configuration details
The official document gives a clear warning:
This custom configuration class cannot be placed under the current package or subpackage scanned by @ComponentScan. Otherwise, our custom configuration class will be shared by all the Ribbon clients, and will not serve the purpose of customization.
(3) the new package
com.atguigu.myrule
(4) Create the MySelfRule rule class
@Configuration
public class MySelfRule{
@Bean
public IRule myRule(a){
return new RandomRule();// Defined as random, the default is polling}}Copy the code
(5) Add @RibbonClient to the main boot class
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration=MySelfRule.class)
Copy the code
(6) test
http://localhost/consumer/payment/get/31
Ribbon load balancing algorithm
1, the principle of
Load balancing algorithm: Number of REST interface requests % Total number of server clusters = the subscript of the actual calling server. The rest interface count starts from 1 after each service restart.
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
Copy the code
For example, List [0] Instances = 127.0.0.1:8002 List [1] Instances = 127.0.0.1:8001
8001+ 8002 is combined into a cluster. There are two machines in total, and the total number of the cluster is 2. According to the polling algorithm principle:
If the total number of requests is 1: 1%2 =1, then the service address is 127.0.0.1:8002. If the total number of requests is 2:2%2 =0, then the service address is 127.0.0.1:8002. If the total number of requests is 3, then the service address is 127.0.0.1:8002. 3%2 =1 corresponds to the subscript position is 1, then the service address is 127.0.0.1:8001. When the total number of requests is 4:4%2 =0 corresponds to the subscript position is 0, the service address is 127.0.0.1:8002 and so on……
2. RoundRobinRule source code
3. Write the local load balancer
(1) Cluster 7001/7002 starts
(2)8001/8002 micro-service transformation
controller
@GetMapping(value = "/payment/lb")
public String getPaymentLB(a){
return serverPort;
}
Copy the code
(3) micro-service transformation of 80 orders
Remove @loadBalanced annotation from ApplicationContextBean
(2) the LoadBalancer interface
public interface LoadBalancer{
ServiceInstance instances(List<ServiceInstance> serviceInstances);
}
Copy the code
(3) MyLB
@Component
public class MyLB implements LoadBalancer{
private AtomicInteger atomicInteger = new AtomicInteger(0);
public final int getAndIncrement(a){
int current;
int next;
do{
current = this.atomicInteger.get();
next = current >= 2147483647 ? 0 : current + 1;
} 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();
returnserviceInstances.get(index); }}Copy the code
(4) OrderController
@RestController
public class OrderController{
//public static final String PAYMENT_SRV = "http://localhost:8001";
public static final String PAYMENT_SRV = "http://CLOUD-PAYMENT-SERVICE";
@Resource
private RestTemplate restTemplate;
// You can get a list of services on the registry
@Resource
private DiscoveryClient discoveryClient;
@Resource
private LoadBalancer loadBalancer;
@GetMapping("/consumer/payment/create")
public CommonResult<Payment> create(Payment payment){
return restTemplate.postForObject(PAYMENT_SRV+"/payment/create",payment,CommonResult.class);
}
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
return restTemplate.getForObject(PAYMENT_SRV+"/payment/get/"+id,CommonResult.class);
}
@GetMapping("/consumer/payment/getForEntity/{id}")
public CommonResult<Payment> getPayment2(@PathVariable("id") Long id){
ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_SRV+"/payment/get/"+id, CommonResult.class);
if(entity.getStatusCode().is2xxSuccessful()){
return entity.getBody();
}else{
return new CommonResult(444."Operation failed"); }}@Resource
private LoadBalancer loadBalancer;
@GetMapping("/consumer/payment/lb")
public String getPaymentLB(a){
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
if(instances == null || instances.size()<=0) {
return null;
}
ServiceInstance serviceInstance = loadBalancer.instances(instances);
URI uri = serviceInstance.getUri();
return restTemplate.getForObject(uri+"/payment/lb",String.class); }}Copy the code
(5) test
http://localhost/consumer/payment/lb
OpenFeign
An overview,
What is OpenFeign
Feign is a declarative Web services client that makes it easy to write Web services clients by simply creating an interface and adding annotations to it.
GitHub:github.com/spring-clou…
2. What can I do
What can Feign do
Feign aims to make it easier to write Java Http clients. When using the Ribbon+RestTemplate, the RestTemplate encapsulates HTTP requests and forms a set of template calling methods. However, in actual development, because service dependencies may be called in more than one place, often an interface will be called in multiple places, so it is common to encapsulate some client classes for each microservice to wrap the invocation of these dependent services. So, Feign took this one step further by helping us define and implement the definition of a dependent service interface. With Feign, we simply create an interface and configure it with an annotation (formerly a Dao interface with a Mapper annotation, now a microservice interface with a Feign annotation) to bind the interface to the service provider. Simplifies the use of Spring Cloud Ribbon to automatically wrap development for service invocation clients.
Feign integrates the Ribbon
The Ribbon is used to maintain the Payment service list information, and the client load balance is realized through polling. Unlike the Ribbon, feign only defines the service binding interface and implements service invocation in a declarative way with elegance and simplicity.
3. Differences between Feign and OpenFeign
Feign | OpenFeign |
---|---|
Feign is a lightweight RESTful HTTP service client in the Spring Cloud component. Feign has built-in Ribbon for client load balancing and calling services in the service registry. Feign is used by using Feign annotations to define an interface that can be invoked to invoke services in the service registry | OpenFeign is Spring Cloud’s support for SpringMVC annotations, such as @requesMapping, on the basis of Feign. OpenFeign’s @FeignClient can parse the interface under SpringMVC’s @RequestMapping annotation and use dynamic proxy to generate implementation classes that perform load balancing and invoke other services |
org.springframework.cloud spring-cloud-starter-feign |
org.springframework.cloud spring-cloud-starter-openfeign |
Second, OpenFeign use steps
Interface + annotations: Microservice invocation interface +@FeignClient
1, create cloud-consumer-Feign-order80
Feign is available on the consumer side
2, POM
<! --openfeign--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <! --eureka client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>Copy the code
3, YML
server:
port: 80
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
Copy the code
4. Main startup
@SpringBootApplication
@EnableFeignClients/ / open
public class OrderFeignMain80 {
public static void main(String[] args) { SpringApplication.run(OrderFeignMain80.class,args); }}Copy the code
5. Business
Service logic interface + @feignClient Configures to invoke the Provider service
(1) Create PaymentFeignService interface and add annotation @feignClient
@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")/ / use
public interface PaymentFeignService {
@GetMapping(value = "/payment/get/{id}")
CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
}
Copy the code
(2) Control layer Controller
@Slf4j
@RestController
public class OrderFeignController {
@Resource
private PaymentFeignService paymentFeignService;
@GetMapping(value = "/consumer/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
returnpaymentFeignService.getPaymentById(id); }}Copy the code
6, test,
To start the first two had 7001/7002 cluster, and then start two micro service 8001/8002, start OpenFeign start, http://localhost/consumer/payment/get/31
Feign Provides load balancing configuration items
Three, OpenFeign timeout control
1, timeout Settings, intentionally set timeout demo error
(1) Service Provider 8001 intentionally writes the pause program
@GetMapping(value = "/payment/feign/timeout")
public String paymentFeignTimeOut(a){
System.out.println("*****paymentFeignTimeOut from port: "+serverPort);
// Pause the thread for a few seconds
try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
return serverPort;
}
Copy the code
(2) Service consumer 80 Add timeout method PaymentFeignService
@GetMapping(value = "/payment/feign/timeout")
String paymentFeignTimeOut(a);
Copy the code
(3) The service consumer 80 adds the timeout method OrderFeignController
@GetMapping(value = "/consumer/payment/feign/timeout")
public String paymentFeignTimeOut(a){
// OpenFeign -ribbon. Clients usually wait one second by default
return paymentFeignService.paymentFeignTimeOut();
}
Copy the code
(4) test
http://localhost/consumer/payment/feign/timeout
By default, OpenFeign will wait 1 second and then report an error
By default, OpenFeign supports the Ribbon
By default, the Feign client waits only one second, but the server takes more than one second to process, causing the Feign client to stop waiting and return an error. To avoid this, sometimes we need to set the Feign client timeout control.
3. OpenFeign client timeout control needs to be enabled in YML files
# Set the feign client timeout period (OpenFeign supports the ribbon by default)
ribbon:
# refers to the time it takes to read the available resources from the server after the connection is established
ReadTimeout: 5000
# refers to the time it takes to establish a connection, which applies to the time it takes for both ends to connect if the network is normal
ConnectTimeout: 5000
Copy the code
Four, OpenFeign log printing function
1. What is it
Feign provides log printing capabilities, which can be configured to adjust the log level to see the details of Http requests in Feign. Basically, it monitors and outputs calls to the Feign interface.
2. Log level
NONE: The default value. No logs are displayed.
BASIC: Records only the request method, URL, response status code, and execution time.
HEADERS: Request and response HEADERS in addition to the information defined in BASIC;
FULL: In addition to the information defined in HEADERS, there is the body and metadata of the request and response.
3. Configure the log bean
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel(a) {
returnLogger.Level.FULL; }}Copy the code
4. YML files need to enable Feign client for logging
logging:
level:
# Feign Logs monitor which interface at what level
com.atguigu.springcloud.service.PaymentFeignService: debug
Copy the code