In Spring Cloud: Micro-service environment (Alibaba), perform stream limiting, downgrade, and fusing

Official document: Sentinelguard. IO /zh-cn/

1. Error message configuration (3. Service fault-tolerant Sentinel)

Goal: Make the flow limiting return information configurable and save it on NACOS

GatewayConfiguration.java

@Configuration
public class GatewayConfiguration {
	private final List<ViewResolver> viewResolvers;
	private final ServerCodecConfigurer serverCodecConfigurer;
        
	/** * Configure traffic limiting */
	@Value("${spring.cloud.sentinel.flow.status}")
	private String flowStatus;
	@Value("${spring.cloud.sentinel.flow.message}")
	private String 	flowMsg;
        @PostConstruct 
        public void initGatewayRules(a) {
            Set<GatewayFlowRule> rules = new HashSet<>(); 
            rules.add( new GatewayFlowRule("Item_route") // Resource name, corresponding route ID
                        .setCount(1) // Traffic limiting threshold
                         .setIntervalSec(1) // Statistics time window, in seconds, default is 1 second
                     );
            GatewayRuleManager.loadRules(rules);
        }
	@PostConstruct
	public void initBlockHandlers(a){
		BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
			@Override
			public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
				Map map = new HashMap<>();
				map.put("code",flowStatus);
				map.put("message",flowMsg);

				returnServerResponse .status(HttpStatus.OK) .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue(map)); }}; GatewayCallbackManager.setBlockHandler(blockRequestHandler); }/** * adds significance to this function: the value can be retrieved from the configuration file (if missing, not available) *@return* /
	@Bean
	public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(a) {
		return new PropertySourcesPlaceholderConfigurer();
	}
Copy the code

Add the following configuration at http://localhost:8848/nacos/

Result: After frequent access

2. Current limiting, downgrading and fusing of Sentinel

Specific reference: cloud.tencent.com/developer/a…

As you can see from the above code, initBlockHandlers are packaged according to the exception type

package com.temp.conf;

import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import lombok.Data;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.List;

@Configuration
public class GatewayConfiguration {
	private final List<ViewResolver> viewResolvers;
	private final ServerCodecConfigurer serverCodecConfigurer;
	/** * limit current */
	@Value("${spring.cloud.sentinel.flow.status}")
	private Integer flowStatus;
	@Value("${spring.cloud.sentinel.flow.message}")
	private String flowMsg;
	/** * demoted */
	@Value("${spring.cloud.sentinel.degrade.status}")
	private Integer degradeStatus;
	@Value("${spring.cloud.sentinel.degrade.message}")
	private String degradeMsg;
	/** * Hotspot parameter limit */
	@Value("${spring.cloud.sentinel.param.flow.status}")
	private Integer paramFlowStatus;
	@Value("${spring.cloud.sentinel.param.flow.message}")
	private String paramFlowMsg;
	/** * System rules (load /... Not meeting the requirements) */
	@Value("${spring.cloud.sentinel.system.block.status}")
	private Integer systemBlockStatus;
	@Value("${spring.cloud.sentinel.system.block.message}")
	private String systemBlockMsg;

	@Value("${spring.cloud.sentinel.authority.status}")
	private Integer authorityStatus;
	@Value("${spring.cloud.sentinel.authority.message}")
	private String authorityMsg;

	public GatewayConfiguration(ObjectProvider
       
        > viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer)
        {
		this.viewResolvers =
				viewResolversProvider.getIfAvailable(Collections::emptyList);
		this.serverCodecConfigurer = serverCodecConfigurer;

	}

	/** * Initialize a current-limiting filter */
	@Bean
	@Order(Ordered.HIGHEST_PRECEDENCE)
	public GlobalFilter sentinelGatewayFilter(a) {
		return new SentinelGatewayFilter();
	}

	/**
	 * Configure current limiting exception handler
	 *
	 * @return SentinelGatewayBlockExceptionHandler
	 */
	@Bean
	@Order(Ordered.HIGHEST_PRECEDENCE)
	public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler(a) {
		return new SentinelGatewayBlockExceptionHandler(
				viewResolvers,
				serverCodecConfigurer
		);
	}

	@PostConstruct
	public void initBlockHandlers(a) {
		BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
			@Override
			public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable e) {

				SentinelErrorMsg sentinelErrorMsg = new SentinelErrorMsg();
					// Flow control is abnormal
				if (e instanceof FlowException) {
					sentinelErrorMsg.setMsg(flowMsg);
					sentinelErrorMsg.setStatus(flowStatus);
					// The exception is degraded
				} else if (e instanceof DegradeException) {
					sentinelErrorMsg.setMsg(degradeMsg);
					sentinelErrorMsg.setStatus(degradeStatus);
					// The parameter flow control is abnormal
				} else if (e instanceof ParamFlowException) {
					sentinelErrorMsg.setMsg(paramFlowMsg);
					sentinelErrorMsg.setStatus(paramFlowStatus);
					// The system is blocked
				} else if (e instanceof SystemBlockException) {
					sentinelErrorMsg.setMsg(systemBlockMsg);
					sentinelErrorMsg.setStatus(systemBlockStatus);
					// Permissions are abnormal
				} else if (e instanceof AuthorityException) {
					sentinelErrorMsg.setMsg(authorityMsg);
					sentinelErrorMsg.setStatus(authorityStatus);
				}

				returnServerResponse .status(HttpStatus.OK) .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue(sentinelErrorMsg)); }}; GatewayCallbackManager.setBlockHandler(blockRequestHandler); }/** * adds significance to this function: the value can be retrieved from the configuration file (if missing, not) **@return* /
	@Bean
	public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(a) {
		return new PropertySourcesPlaceholderConfigurer();
	}

	/** * Error message */
	@Data
	static class SentinelErrorMsg {
		private Integer status;
		privateString msg; }}Copy the code

3. Sentinel console 1.8.1 control

If you don’t see the project you should see on Sentinel, follow these steps

Execution parameters:

-Dcsp.sentinel.app.type=1 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=alibaba-gateway

-dcsp.sentinel.app. type=1 Traffic limiting of the gateway.

If not, clear the browser cache. Because Sentinel is lazy loading, you need to execute the specific API and then refresh.

3.1 the flow control

Note: When doing gateway flow control, remember to use the defined routId instead of the corresponding API address

Flow control rule setting

When accessing a link under this routeID, it acts as a lower bound stream:

3.2 the drop

bug:Bbs.huaweicloud.com/blogs/20606…Note: There is a bug in the degraded page of Sentinel Dashboard in version 1.8.0, which is missing the maintenance of statistics duration properties. It is expected to be fixed in the next release

Need to switch to version 1.8.1, fix this bug

3.2.1 Service: /item/{id}

@RestController
public class ItemController {
	@Autowired
	private ItemService itemService;

	@RequestMapping("/item/{id}")
	public Item query(@PathVariable Long id) {

		// Let the service sleep for 10 seconds
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return itemService.queryItemById(id);
	}

	@RequestMapping("/item/change/{id}/{order_id}")
	public Item saveOrderId(@PathVariable("id") Long id,@PathVariable("order_id") Long orderId) {
		returnitemService.saveOrderId(id,orderId); }}Copy the code

Restart the temp-item project

3.2.2 Degrade the Configuration

Configuration dialog box

After the Settings are saved, the degradation rules take effect

3.2.3 test

On the first visit, the results came out 10 seconds later

But after refreshing again, the service becomes degraded

Note: The access will be restored 10 seconds later

It takes slightly more time to persist this part of the configuration from here. I’ll write another one for now