This is the 15th day of my participation in the August More Text Challenge. For details, see:August is more challenging

juejin.cn/post/699552…

Effect of flow control

Fail fast

Direct throw exception

Warm UP

The system is given a preheating time. During the preheating time, the single-node threshold is low, but after the preheating time, the single-node threshold increases. During the preheating time, the current single-node threshold is one third of the set threshold, and after the preheating time, the single-node threshold restores to the set value.

Waiting in line

When the request fails, the exception is not thrown immediately, waiting for the next call, the time range is timeout, within the time range if the request succeeds, the exception is not thrown, if the request is thrown.

Drop rules

RT

If the response time of a single request exceeds the threshold, the request enters the quasi-degradation state. If the response time of five consecutive requests exceeds the threshold within 1 second, the request is degraded. The duration is the value of the time window.

Abnormal proportion

If the proportion of the number of exceptions per second to the number of passes is greater than the threshold, the degradation process is performed. The duration is the value of the time window.

Number of abnormal

If the number of exceptions within one minute exceeds the threshold, the system degrades. The value of the time window must be greater than 60S. Otherwise, the system enters the next circuit breaker just after the circuit breaker ends.

Hot rules

A hotspot rule is a more fine-grained operation of a flow control rule. You can specify the traffic limiting for a hotspot parameter. After the traffic limiting is set, if the number of requests with the traffic limiting parameter exceeds the threshold, the traffic limiting is performed.

You have to add @SentinelResource, which flows the resource.

@GetMapping("/hot")
@SentinelResource("hot")
public String hot(
        @RequestParam(value = "num1",required = false) Integer num1,
        @RequestParam(value = "num2",required = false) Integer num2){
    return num1+"-"+num2;
}
Copy the code

Authorization rules

When you set the flow control application for a specified resource (by adding parameters), you can set the access permission for the flow control application by adding whitelists and blacklists.

To specify a flow control application for a request, implement the RequestOriginParser interface as shown below.

package com.southwind.configuration; import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser; import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; public class RequestOriginParserDefinition implements RequestOriginParser { @Override public String parseOrigin(HttpServletRequest httpServletRequest) { String name = httpServletRequest.getParameter("name"); if(StringUtils.isEmpty(name)){ throw new RuntimeException("name is null"); } return name; }}Copy the code

To make RequestOriginParserDefinition effect, need to be configured in the configuration class.

package com.southwind.configuration; import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager; import org.springframework.context.annotation.Configuration; import javax.annotation.PostConstruct; @Configuration public class SentinelConfiguration { @PostConstruct public void init(){ WebCallbackManager.setRequestOriginParser(new RequestOriginParserDefinition()); }}Copy the code

An exception of a custom rule is returned

Create an exception handling class

package com.southwind.handler; import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlBlockHandler; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException; import com.alibaba.csp.sentinel.slots.block.flow.FlowException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class ExceptionHandler implements UrlBlockHandler { @Override public void blocked(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws IOException { httpServletResponse.setContentType("text/html; charset=utf-8"); String msg = null; If (e instanceof FlowException){MSG = "limit FlowException "; }else if(e instanceof DegradeException){MSG = "degrade "; } httpServletResponse.getWriter().write(msg); }}Copy the code

Perform configuration.

@Configuration public class SentinelConfiguration { @PostConstruct public void init(){ WebCallbackManager.setUrlBlockHandler(new ExceptionHandler()); }}Copy the code

Integrated RocketMQ

Install RocketMQ

1. Pass it to the Linux server

2. Decompress

Unzip rocketmq - all - 4.7.1 - bin - release. ZipCopy the code

3. Start NameServer

nohup ./bin/mqnamesrv &
Copy the code

4. Check whether the startup is successful

netstat -an | grep 9876
Copy the code

5. Start Broker

Before starting, we need to edit the configuration file and modify the JVM memory Settings. The default memory is 4 GB, which is more than our JVM.

cd bin
vim runserver.sh
Copy the code
vim runbroker.sh
Copy the code

Start the Broker

nohup ./mqbroker -n localhost:9876 &
Copy the code

You can view logs

tail -f ~/logs/rocketmqlogs/broker.log
Copy the code

Start-up success

Test RocketMQ

Message is sent

cd bin
export NAMESRV_ADDR=localhost:9876
./tools.sh org.apache.rocketmq.example.quickstart.Producer
Copy the code

The message received

cd bin
export NAMESRV_ADDR=localhost:9876
./tools.sh org.apache.rocketmq.example.quickstart.Consumer
Copy the code

7. Close RocketMQ

cd bin
./mqshutdown broker
./mqshutdown namesrv
Copy the code

Install the RocketMQ console

1. Decompress, modify the configuration, and package

mvn clean package -Dmaven.test.skip=true
Copy the code

2. Enter target to start jar

Java jar rocketmq - the console - ng - 1.0.0. JarCopy the code

Open the browser to localhost:9877, if the error

This is because our RocketMQ is installed in Linux and the console is on Windows, and Linux requires open ports for access, opening ports 10909 and 9876

firewall-cmd --zone=public --add-port=10909/tcp --permanent
firewall-cmd --zone=public --add-port=9876/tcp --permanent
systemctl restart firewalld.service
firewall-cmd --reload
Copy the code

Restart the console project

Java implements message sending

1. Import dependencies into POM.xml

<dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-spring-boot-starter</artifactId> The < version > 2.1.0 < / version > < / dependency >Copy the code

2. Production messages

package com.southwind; import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.client.producer.SendResult; import org.apache.rocketmq.common.message.Message; Public class Test {public static void main(String[] args) throws Exception {// Create message producer DefaultMQProducer Producer = new  DefaultMQProducer("myproducer-group"); // Set NameServer producer.setNamesrvAddr("192.168.248.129:9876"); // Start the producer. Start (); Message Message = new Message("myTopic","myTag",("Test MQ").getBytes()); SendResult result = producer.send(message, 1000); System.out.println(result); // shutdown the producer. Shutdown (); }}Copy the code

3, run directly, if sendDefaultImpl call Timeout error, can open port 10911

firewall-cmd --zone=public --add-port=10911/tcp --permanent
systemctl restart firewalld.service
firewall-cmd --reload
Copy the code

Open the RocketMQ console to view the messages.

Java implements message consumption

package com.southwind.service; import lombok.extern.slf4j.Slf4j; import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.common.message.MessageExt; import java.util.List; @slf4j public class ConsumerTest {public static void main(String[] args) throws MQClientException {// Create a message consumer DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("myconsumer-group"); // Set NameServer consumer.setNamesrvAddr("192.168.248.129:9876"); Consumer. Subscribe ("myTopic","*"); / / callback function consumer. RegisterMessageListener (new MessageListenerConcurrently () {@ Override public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) { log.info("Message=>{}",list); return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; }}); // Start consumer. Start (); }}Copy the code

Spring Boot is integrated with RocketMQ

provider

1, pom. XML

<dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-spring-boot-starter</artifactId> < version > 2.1.0 < / version > < / dependency > < the dependency > < groupId > org. Apache. Rocketmq < / groupId > < artifactId > rocketmq - client < / artifactId > < version > 4.7.0 < / version > < / dependency >Copy the code

2, application. Yml

Rocketmq: name-server: 192.168.248.129:9876 Producer: group: myproviderCopy the code

3, the Order

package com.southwind.entity;
​
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
​
import java.util.Date;
​
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {
    private Integer id;
    private String buyerName;
    private String buyerTel;
    private String address;
    private Date createDate;
}
Copy the code

4, the Controller

@Autowired private RocketMQTemplate rocketMQTemplate; @getMapping ("/create") public Order create(){Order Order = new Order(1, "123123", "software Park ", new Date()); this.rocketMQTemplate.convertAndSend("myTopic",order); return order; }Copy the code

consumer

1, pom. XML

<dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-spring-boot-starter</artifactId> < version > 2.1.0 < / version > < / dependency > < the dependency > < groupId > org. Apache. Rocketmq < / groupId > < artifactId > rocketmq - client < / artifactId > < version > 4.7.0 < / version > < / dependency >Copy the code

2, application. Yml

Rocketmq: name - server: 192.168.248.129:9876Copy the code

3, the Service

@Slf4j @Service @RocketMQMessageListener(consumerGroup = "myConsumer",topic = "myTopic") public class SmsService Implements RocketMQListener<Order> {@override public void onMessage(Order Order) {log.info(" new Order {}, SMS ", Order); }}Copy the code

The service gateway

The Spring Cloud Gateway is based on Netty and is not compatible with servlets, so you cannot have servlets in your project.

1, pom. XML

Note that spring Web dependencies must not occur, because the Gateway is not compatible with servlets.

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
Copy the code

2, application. Yml

server:
  port: 8010
spring:
  application:
    name: gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes: 
        - id: provider_route   
          uri: http://localhost:8081 
          predicates: 
            - Path=/provider/** 
          filters:
            - StripPrefix=1
Copy the code

This does not actually use nacos. Now we have the Gateway go directly to nacOS to find services, which makes configuration easier.

1. Pom. XML is introduced to NACOS

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

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
Copy the code

2, application. Yml

server:
  port: 8010
spring:
  application:
    name: gateway
  cloud:
      gateway:
        discovery:
          locator:
            enabled: true
Copy the code

Gateway current-limiting

Routing based traffic limiting

1, pom. XML

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
​
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
Copy the code

2. Configuration

@Configuration public class GatewayConfiguration { private final List<ViewResolver> viewResolvers; private final ServerCodecConfigurer serverCodecConfigurer; public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) { this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList); this.serverCodecConfigurer = serverCodecConfigurer; } / / configure current-limiting exception handling @ Bean @ Order (Ordered. HIGHEST_PRECEDENCE) public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() { return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer); } @postConstruct public void initGatewayRules(){Set<GatewayFlowRule> rules = new HashSet<>(); rules.add( new GatewayFlowRule("provider_route") .setCount(1) .setIntervalSec(1) ); GatewayRuleManager.loadRules(rules); } @bean @order (Ordered.highest_precedence) public GlobalFilter sentinelGatewayFilter() {return new SentinelGatewayFilter(); } @postconstruct public void initBlockHandlers(){BlockRequestHandler BlockRequestHandler = new BlockRequestHandler() { @Override public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) { Map map = new HashMap(); map.put("code",0); Map.put (" MSG "," restricted stream "); return ServerResponse.status(HttpStatus.OK) .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromObject(map)); }}; GatewayCallbackManager.setBlockHandler(blockRequestHandler); }}Copy the code

3, application. Yml

server:
  port: 8010
spring:
  application:
    name: gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: provider_route
          uri: http://localhost:8081
          predicates:
            - Path=/provider/**
          filters:
            - StripPrefix=1
Copy the code