Leader 1-to-1 micro service system Solar | Alibaba Sentinel landing practice

preface

In recent years, the business of leader 1-to-1 has been developing rapidly, but at the same time, he has encountered "growing pains". With the increasing number of microservices, the traffic further increases, and the hardware resources are a little overwhelmed. Then, how to achieve better flow protection measures such as current limiting, fusing and degradation is the topic in front of the leader. As the Spring Cloud system has evolved to the second generation, the first generation of Hystrix current limiting fuse degradation component is not suitable for the current business logic and scale. At the same time, it is officially placed in the maintenance mode by Spring Cloud and will not move forward.

How to choose a better current limiting fuse degradation component? After in-depth research and comparison of Alibaba Sentinel, Resilience4j, Hystrix and other open-source components, Alibaba Sentinel was selected as the required component for current limiting and downgrading in the micro service system Solar.

About Sentinel

Alibaba middleware department develops a new generation of traffic protection guards for distributed systems that protect the stability of services from multiple dimensions, such as traffic control, fuse degradation, system load protection, etc. It has undertaken the core scenarios of Alibaba's "double 11" traffic promotion in the past 10 years, such as seckill (i.e. sudden flow control within the range of system capacity), message peak cutting and valley filling, cluster flow control, real-time fuse downstream unavailable applications, etc.

It has a very rich open source ecosystem:

Compared with Hystrix, it has the following differences:

From official website Sentinel Roadmap

How to use Sentinel and how its principle of technology implementation can be achieved, official documents or folk blogs, official account articles can provide very detailed and valuable materials. The author tries to combine the existing technology stack and middleware integration strategy of leader 1, and focuses on the powerful Spring Cloud Alibaba technology ecosystem.

Sentinel deep integration Apollo

Sentinel has extended Apollo in the sentinel data source Apollo module, which mainly implements the reading and subscription logic of sentinel rules. These are not enough. We need to integrate Apollo at a deeper level.

From official website Using Sentinel in a production environment

Solar SDK environment initialization

Customize the EnvironmentPostProcessor class, and the implementation is as follows:

  • The project name of Sentinel Dashboard is displayed from the dimension of Apollo AppId
  • Read the corresponding configuration file according to the env value of the environment, and access the Sentinel Dashboard domain name of the corresponding environment. Deploy several ECS instances in the production environment. Alicloud SLB performs load balancing to realize the horizontal expansion of the cluster
public class SentinelClientEnvironmentPostProcessor implements EnvironmentPostProcessor {
    private final ResourceLoader resourceLoader = new DefaultResourceLoader();
    private static final String DEFAULT_CLASSPATH_LOCATION = "classpath:/META-INF/app.properties";
    private static final String DEFAULT_LOCATION = "/META-INF/app.properties";
    private static final String DEFAULT_LOG_LOCATION = "/opt/logs/";    

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        try {
            Resource appResource = resourceLoader.getResource(DEFAULT_CLASSPATH_LOCATION);
            if (!appResource.exists()) {
                appResource = resourceLoader.getResource(DEFAULT_LOCATION);
            }

            Properties appProperties = new Properties();
            appProperties.load(new InputStreamReader(appResource.getInputStream()));
            String appId = appProperties.getProperty("app.id");
            System.setProperty("project.name", appId);
            System.setProperty("csp.sentinel.log.dir", DEFAULT_LOG_LOCATION + appId);

            Properties properties = new Properties();

            String path = isOSWindows() ? "C:/opt/settings/server.properties" : "/opt/settings/server.properties";
            File file = new File(path);
            if (file.exists() && file.canRead()) {
                FileInputStream fis = new FileInputStream(file);
                if (fis != null) {
                    try {
                        properties.load(new InputStreamReader(fis, Charset.defaultCharset()));
                    } finally {
                        fis.close();
                    }
                }
            }

            String idc = properties.getProperty("idc");
            String location;
            String env = System.getProperty("env");
            if (StringUtils.isEmpty(idc)) {
                if (!isBlank(env)) {
                    env = env.trim().toLowerCase();
                } else {
                    env = System.getenv("ENV");
                    if (!isBlank(env)) {
                        env = env.trim().toLowerCase();
                    } else {
                        env = properties.getProperty("env");
                        if (!isBlank(env)) {
                            env = env.trim();
                        } else {
                            env = Env.FAT.getEnv();
                        }
                    }
                }

                location = "classpath:/META-INF/sentinel-" + env + ".properties";
            } else {
                location = "classpath:/META-INF/sentinel-" + idc + ".properties";
            }

            Resource serverResource = resourceLoader.getResource(location);
            properties.load(new InputStreamReader(serverResource.getInputStream()));
            for (String key : properties.stringPropertyNames()) {
                System.setProperty(key, properties.getProperty(key));
            }

            System.setProperty(CommonConstant.SENTINEL_VERSION_NAME, CommonConstant.SENTINEL_VERSION_VALUE);
        } catch (Exception e) {
            LOG.error(e.getMessage());
        }
    }

    private boolean isBlank(String str) {
        return Strings.nullToEmpty(str).trim().isEmpty();
    }

    private boolean isOSWindows() {
        String osName = System.getProperty("os.name");

        return !isBlank(osName) && osName.startsWith("Windows");
    }
}

Place the SentinelClientEnvironmentPostProcessor class in the file \ resources\META-INF\spring.factories, and the content is

org.springframework.boot.env.EnvironmentPostProcessor=\
com.zhangmen.solar.component.sentinel.common.context.SentinelClientEnvironmentPostProcessor

In the directory of \ resources\META-INF, customize the environment configuration file. The file name format is Sentinel - {environment number}. properties. The following is an example of dev environment and flow flow control configuration (for other rule configurations, please refer to the relevant materials of Spring Cloud Alibaba Sentinel).

sentinel-dev.properties

spring.cloud.sentinel.transport.dashboard=127.0.0.1:8080
spring.cloud.sentinel.datasource.ds.apollo.namespaceName=application
spring.cloud.sentinel.datasource.ds.apollo.flowRulesKey=sentinel.flowRules
spring.cloud.sentinel.datasource.ds.apollo.ruleType=flow
...

Sentinel Dashboard persistent transformation

After the native Sentinel Dashboard creates the rule, the rule content is saved in the memory of the service. When the service is restarted, all rule content will disappear. Therefore, configuration persistence should be considered in production deployment, and the awareness of Apollo dynamic rules should be used.

① Restful interface to expose Sentinel rules outwards

@RestController
@RequestMapping(value = "/v2/flow")
public class FlowControllerV2 {
    @Autowired
    @Qualifier("apolloFlowRuleProvider")
    private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;

    @Autowired
    @Qualifier("apolloFlowRulePublisher")
    private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
    ....
}

② Implementation of Sentinel Apollo rule provision

@Component("apolloFlowRuleProvider")
public class ApolloFlowRuleProvider extends BaseApolloRuleProvider<FlowRuleEntity> {
    @Override
    public List<FlowRuleEntity> getRules(String appName) throws Exception {
        List<FlowRuleEntity> flowRuleEntityList = super.getRules(appName);
        if (!CollectionUtils.isEmpty(flowRuleEntityList)) {
            List<FlowRuleEntity> flowRuleEntities = JSONArray.parseArray(flowRuleEntityList.toString(), FlowRuleEntity.class);
            long id = 1;
            for (FlowRuleEntity entity : flowRuleEntities) {
                entity.setId(id++);
                entity.getClusterConfig().setFlowId(entity.getId());
            }
            return flowRuleEntities;
        } else {
            return null;
        }
    }

    @Override
    protected String getDataId() {
        return ApolloConfigUtil.getFlowDataId();
    }
}

③ Implement Sentinel Apollo rule subscription

@Component("apolloFlowRulePublisher")
public class ApolloFlowRulePublisher extends BaseApolloRulePublisher<List<FlowRuleEntity>> {
    @Override
    public void publish(String app, String operator, List<FlowRuleEntity> rules) throws Exception {
        if (!CollectionUtils.isEmpty(rules)) {
            for (int i = 0; i < rules.size(); i++) {
                rules.get(i).setId((long) (i + 1));
                rules.get(i).setApp(null);
                rules.get(i).setGmtModified(null);
                rules.get(i).setGmtCreate(null);
                rules.get(i).setIp(null);
                rules.get(i).setPort(null);

                rules.get(i).getClusterConfig().setFlowId((long) (i + 1));
            }
        } else {
            rules = null;
        }

        super.publish(app, operator, rules);
    }

    @Override
    protected String getDataId() {
        return ApolloConfigUtil.getFlowDataId();
    }
}

The above code implements the reading and writing operation of Apollo configuration. Students familiar with Apollo should know that these operations need to be operated based on Apollo OpenApi; the logic of dynamic perception has been implemented by sentinel datasource Apollo module.

Sentinel integrated Skywalking

As the leader 1-1 micro service technology stack landed earlier, and in view of historical limitations (there was no more advanced technology to choose at that time), in addition to the older Hystrix, the pain point of another technology stack is that the transformation of full link monitoring middleware is also on the agenda, CAT As a well-known work in the open source industry, it provides a strong guarantee for the company's bottom layer full link monitoring. However, with the evolution of technology, it is gradually not suitable for the company's future development direction. After comparison, Skywalking will be selected as its replacement (for Skywalking technology selection, it will be in the back of the leader's 1-to-1 micro service system Solar The official account of the series will be explained in detail.

The service system requires real-time burying points of the whole link for current limiting fuse degradation, and hopes to provide multidimensional statistics of current limiting fuse degradation burying points on Skywalking interface. Because Skywalking implements opentracking standardization protocol, it is a good technology choice to output Sentinel embedded point to Skywalking Server through Solar SDK with opentracking as a bridge. The following is a brief introduction of the SPI mechanism based on Sentinel InitFunc to realize the embedded point output:

Sentinel extends the ProcessorSlot as an SPI interface (SlotChainBuilder as SPI before version 1.7.2), which makes the Slot Chain have the ability of extension. You can add custom slots and arrange the order of slots by yourself, so that you can add custom functions to sentinel.

From official website Sentinel work main process

Abstract Sentinel ProcessorSlot buried point output

Sentinel's ProcessorSlotEntryCallback provides two methods, onPass and onBlocked. After all, current limiting and fusing degradation is not a normal function and will not occur in large traffic, so we do not do any processing on onPass, otherwise normal calls to achieve interception will generate a large number of embedded data, which will put Skywalking Server under great performance pressure, so onBlocked will be our focus. In addition to outputting the context parameters of sentinel itself, it will also output the Solar indicator parameters of microservice, mainly including:

  • The name of the buried point Span, here is SENTINEL. In the Skywalking full link monitoring interface, users can easily find this buried point
  • The group name of the service, which refers to the logical grouping of the service
  • Service type, including service and gateway (gateway is also a special service), Sentinel embedded point can support output on service and gateway
  • APPID of service, which is the category concept of Apollo component
  • Service name, which corresponds to the configuration value of spring.application.name
  • IP address and Port port of the service instance
  • Service version number
  • Service area
  • Sub environment of the service

Next are Sentinel level parameters. Please refer to Sentinel official documents and source codes for their meanings. We will not explain them in detail here.

public abstract class SentinelTracerProcessorSlotEntryCallback<S> implements ProcessorSlotEntryCallback<DefaultNode> {
    @Override
    public void onPass(Context context, ResourceWrapper resourceWrapper, DefaultNode param, int count, Object... args) throws Exception {

    }

    @Override
    public void onBlocked(BlockException e, Context context, ResourceWrapper resourceWrapper, DefaultNode param, int count, Object... args) {
        S span = buildSpan();

        PluginAdapter pluginAdapter = PluginContextAware.getStaticApplicationContext().getBean(PluginAdapter.class);

        outputSpan(span, DiscoveryConstant.SPAN_TAG_PLUGIN_NAME, context.getName());
        outputSpan(span, DiscoveryConstant.N_D_SERVICE_GROUP, pluginAdapter.getGroup());
        outputSpan(span, DiscoveryConstant.N_D_SERVICE_TYPE, pluginAdapter.getServiceType());
        String serviceAppId = pluginAdapter.getServiceAppId();
        if (StringUtils.isNotEmpty(serviceAppId)) {
            outputSpan(span, DiscoveryConstant.N_D_SERVICE_APP_ID, serviceAppId);
        }
        outputSpan(span, DiscoveryConstant.N_D_SERVICE_ID, pluginAdapter.getServiceId());
        outputSpan(span, DiscoveryConstant.N_D_SERVICE_ADDRESS, pluginAdapter.getHost() + ":" + pluginAdapter.getPort());
        outputSpan(span, DiscoveryConstant.N_D_SERVICE_VERSION, pluginAdapter.getVersion());
        outputSpan(span, DiscoveryConstant.N_D_SERVICE_REGION, pluginAdapter.getRegion());
        outputSpan(span, DiscoveryConstant.N_D_SERVICE_ENVIRONMENT, pluginAdapter.getEnvironment());

        outputSpan(span, SentinelStrategyConstant.ORIGIN, context.getOrigin());
        outputSpan(span, SentinelStrategyConstant.ASYNC, String.valueOf(context.isAsync()));
        outputSpan(span, SentinelStrategyConstant.RESOURCE_NAME, resourceWrapper.getName());
        outputSpan(span, SentinelStrategyConstant.RESOURCE_SHOW_NAME, resourceWrapper.getShowName());
        outputSpan(span, SentinelStrategyConstant.RESOURCE_TYPE, String.valueOf(resourceWrapper.getResourceType()));
        outputSpan(span, SentinelStrategyConstant.ENTRY_TYPE, resourceWrapper.getEntryType().toString());
        outputSpan(span, SentinelStrategyConstant.RULE_LIMIT_APP, e.getRuleLimitApp());
        if (tracerSentinelRuleOutputEnabled) {
            outputSpan(span, SentinelStrategyConstant.RULE, e.getRule().toString());
        }
        outputSpan(span, SentinelStrategyConstant.CAUSE, e.getClass().getName());
        outputSpan(span, SentinelStrategyConstant.BLOCK_EXCEPTION, e.getMessage());
        outputSpan(span, SentinelStrategyConstant.COUNT, String.valueOf(count));
        if (tracerSentinelArgsOutputEnabled) {
            outputSpan(span, SentinelStrategyConstant.ARGS, JSON.toJSONString(args));
        }

        finishSpan(span);
    }

    protected abstract S buildSpan();

    protected abstract void outputSpan(S span, String key, String value);

    protected abstract void finishSpan(S span);
}

Integrating opentracking & skywalking

There are three core methods to implement sentineltracerprocessor slotentrycallback:

  • buildSpan - creates a buried point Span object for Skywalking
  • outputSpan - output the key value pairs of relevant embedded point data to the embedded point Span object of Skywalking
  • finishSpan - submit the embedded point Span object of Skywalking to Skywalking Server
public class SentinelSkywalkingTracerProcessorSlotEntryCallback extends SentinelTracerProcessorSlotEntryCallback<Span> {
    private Tracer tracer = new SkywalkingTracer();
    
    @Override
    protected Span buildSpan() {
        return tracer.buildSpan(SentinelStrategyConstant.SPAN_NAME).startManual();
    }

    @Override
    protected void outputSpan(Span span, String key, String value) {
        span.setTag(key, value);
    }

    @Override
    protected void finishSpan(Span span) {
        span.finish();
    }
}

Implementation of Sentinel InitFunc SPI extension

Extension entry class for SPI implementation

public class SentinelSkywalkingTracerInitFunc implements InitFunc {
    @Override
    public void init() throws Exception {
        StatisticSlotCallbackRegistry.addEntryCallback(SentinelSkywalkingTracerProcessorSlotEntryCallback.class.getName(), new SentinelSkywalkingTracerProcessorSlotEntryCallback());
    }
}

Place the SPI extension pointcut class in the file \ resources\META-INF\services\com.alibaba.csp.sentinel.init.InitFunc, and the content is

com.nepxion.discovery.plugin.strategy.sentinel.skywalking.monitor.SentinelSkywalkingTracerInitFunc

From Nepxion Discovery open source community

For the integration of Sentinel with opentracking, Skywalking and Jaeger, please refer to https://github.com/Nepxion/Discovery The modules of discovery plugin strategy sentinel starter opentracking, discovery plugin strategy sentinel starter skywalking, etc.

Finally, the output on Skywalking full link interface is as follows:

In the whole link call chain, we can see that the sentinel embedded point is output on the link of the solar-service-a service, indicating that one of the sentinel current limiting and fusing degradation events occurred on the solar-service-a.

Click the SENTINEL burying point, and on the called content Kanban, we can see that the solar-service-a service has a flow restriction event, which shows a series of parameters such as the flow restriction rules and exception information as well as the micro service Solar indicator.

We can click [fuse query] on the interface to analyze and count Sentinel related data

Sentinel integrated influxdb & grafana

Persistent monitoring data to InfluxDB

① Sentinel MetricFetcher pull data

Realize the Dashboard server pulling the monitoring data of Sentinel client (Solar microservice)

@Component
public class MetricFetcher {
    @Autowired
    @Qualifier("influxDBMetricRepository")
    private MetricsRepository<MetricEntity> metricStore;
    ...
}

② InfluxDB instance initialization

@Configuration
public class InfluxDBAutoConfiguration {
    @Value("${spring.influx.url}")
    private String influxDBUrl;

    @Value("${spring.influx.user}")
    private String userName;

    @Value("${spring.influx.password}")
    private String password;

    @Value("${spring.influx.database}")
    private String database;

    @Bean
    public InfluxDB influxDB() {
        InfluxDB influxDB = null;
        try {
            influxDB = InfluxDBFactory.connect(influxDBUrl, userName, password);
            influxDB.setDatabase(database).enableBatch(100, 1000, TimeUnit.MILLISECONDS);
            influxDB.setLogLevel(InfluxDB.LogLevel.NONE);
        } catch (Exception e) {
            LOG.error(e.getMessage());
        }

        return influxDB;
    }
}

③ Sentinel data written to InfluxDB

@Component("influxDBMetricRepository")
public class InfluxDBMetricRepository implements MetricsRepository<MetricEntity> {
    @Autowired
    private InfluxDB influxDB;

    @Override
    public void save(MetricEntity metric) {
        try {
            Point point = createPoint(metric);
            influxDB.write(point);
        } catch (Exception e) {
            LOG.error(e.getMessage());
        }
    }

    @Override
    public void saveAll(Iterable<MetricEntity> metrics) {
        if (metrics == null) {
            return;
        }

        try {
            BatchPoints batchPoints = BatchPoints.builder().build();
            metrics.forEach(metric -> {
                Point point = createPoint(metric);
                batchPoints.point(point);
            });

            influxDB.write(batchPoints);
        } catch (Exception e) {
            LOG.error(e.getMessage());
        }
    }
}

Grafana interface shows monitoring data

Sentinel limit app fuse extension

The leader 1-to-1 has realized the precise guidance and allocation of traffic through the gray-scale blue-green release mode, but in order to further implement more secure traffic protection, the fuse of basic indicators and gray-scale blue-green release indicators is introduced, and the fuse of business user-defined indicators and composite indicators is also supported.

Through the extension of sentinel limit app mechanism and customization of authorization rules, the fuse extension of microservice Solar is realized. The parameters involved in the authorization rules are briefly described as follows:

  • resource is the value of the @ SentinelResource annotation, or the URL path value of the call
  • If there are multiple limitapps, they can be separated by. In particular, for the sake of simplicity, the following is just a single example
  • A strategy of 0 indicates a white list, and traffic will be released if it meets the conditions; a strategy of 1 indicates a black list, and traffic will be limited if it meets the conditions. In particular, for the sake of simplicity, the following is just a white list

Fusing of basic indexes

Through the way that Http Header automatically carries the basic indicators of downstream services for full link transmission, the basic indicators of downstream calls are fused. The following indicators are supported:

① Service name

When A service sends A request to B service and the A service name carried does not meet the conditions, the request will be fused by B service.

  • Add configuration item for service B
spring.application.strategy.service.sentinel.request.origin.key=n-d-service-id
  • Add authorization rules for service B, limitApp is service A name
[
    {
        "resource": "sentinel-resource",
        "limitApp": "a-service-id",
        "strategy": 0
    }
]

② APPID of service

When A service sends A request to B service, the APPID of the carried A service does not meet the conditions, the request will be fused by B service.

  • Add configuration item for service B
spring.application.strategy.service.sentinel.request.origin.key=n-d-service-app-id
  • Authorization rules are added for service B, and limitApp is APPID of service A
[
    {
        "resource": "sentinel-resource",
        "limitApp": "a-service-app-id",
        "strategy": 0
    }
]

③ IP address and Port port of the service instance

When A service sends A request to B service, the IP address and Port port of the carried A service do not meet the conditions, the request will be fused by B service.

  • Add configuration item for service B
spring.application.strategy.service.sentinel.request.origin.key=n-d-service-address
  • Add authorization rules for service B. limitApp is the IP address and Port of service A instance
[
    {
        "resource": "sentinel-resource",
        "limitApp": "a-ip:a-port",
        "strategy": 0
    }
]

The fuse of gray blue green release index

Through the way that Http Header automatically carries the gray-scale blue-green release index of the downstream service for full link transmission, the gray-scale blue-green release index of the downstream call is fused. The following indicators are supported:

① Group name of the service

When A service sends A request to B service, the group name of the carried A service is inconsistent with the group name of B service, and the request will be blown by B service.

  • Add configuration item for service B
spring.application.strategy.service.sentinel.request.origin.key=n-d-service-group
  • Add authorization rule for service B, limitApp is the group name of service B
[
    {
        "resource": "sentinel-resource",
        "limitApp": "b-group",
        "strategy": 0
    }
]

② Service version number

When A service sends A request to B service, the version number of the carried A service is inconsistent with the version number of B service, and the request will be blown by B service.

  • Add configuration item for service B
spring.application.strategy.service.sentinel.request.origin.key=n-d-service-version
  • Add authorization rules for service B, limitApp is the version number of service B
[
    {
        "resource": "sentinel-resource",
        "limitApp": "b-version",
        "strategy": 0
    }
]

③ Service area

When A service sends A request to B service, the region value of A service carried is inconsistent with that of B service, and the request will be fused by B service.

  • Add configuration item for service B
spring.application.strategy.service.sentinel.request.origin.key=n-d-service-region
  • Add authorization rules for service B. limitApp is the regional value of service B
[
    {
        "resource": "sentinel-resource",
        "limitApp": "b-region",
        "strategy": 0
    }
]

④ Sub environment of the service

When A service sends A request to B service, the sub environment value of the carried A service is inconsistent with that of B service, and the request will be fused by B service.

  • Add configuration item for service B
spring.application.strategy.service.sentinel.request.origin.key=n-d-service-env
  • Add authorization rules for service B. limitApp is the sub environment value of service B
[
    {
        "resource": "sentinel-resource",
        "limitApp": "b-env",
        "strategy": 0
    }
]

Fusing of business custom indicators

Through the way that Http Header carries the customized service indicators of downstream services for full link transmission, the customized indicators are fused for downstream calls.

When the A service sends A request to the B service, the user-defined index of A carried by it does not meet the conditions, the request will be fused by the B service. For example: the A service passes the userName to the B service through the Http Header, while the B service only accepts the request with the userName of zhangsan. Then we can solve this problem by the following methods:

  • B service implements the parsing of Sentinel Origin value through adaptation class
public class MyServiceSentinelRequestOriginAdapter extends AbstractServiceSentinelRequestOriginAdapter {
    @Override
    public String parseOrigin(HttpServletRequest request) {
        return request.getHeader("userName");
    }
}
  • The configuration class of service B is created by @ Bean mode
@Bean
public ServiceSentinelRequestOriginAdapter ServiceSentinelRequestOriginAdapter() {
    return new MyServiceSentinelRequestOriginAdapter();
}
  • Add authorization rules for service B. the limitApp is zhangsan
[
    {
        "resource": "sentinel-resource",
        "limitApp": "zhangsan",
        "strategy": 0
    }
]

If this method still fails to meet the business scenario, the business system hopes to obtain the userType according to the userName, and make a unified fuse according to the user type. For example, the request with the user type of auto user can be released, and the others can be fused. Then we can modify the above example as follows:

  • The adaptation class of B service is changed as follows:
public class MyServiceSentinelRequestOriginAdapter extends AbstractServiceSentinelRequestOriginAdapter {
    @Override
    public String parseOrigin(HttpServletRequest request) {
        String userName = request.getHeader("userName");
        String userType = getUserTypeByName(userName);        

        return userType;
    }
}
  • The authorization rules of B service are changed as follows:
[
    {
        "resource": "sentinel-resource",
        "limitApp": "AUTH_USER",
        "strategy": 0
    }
]

Fuse of combination index

Through the way that Http Header carries the business user-defined indicators, basic indicators or gray blue-green release indicators of downstream services for full link transmission, fuse the combination indicators of downstream calls. For example, fuse them together according to the incoming microservice version number + user name. The following example shows that the downstream service version is 1.0 and the userName is zhangsan. If both conditions are met, all service requests are allowed to be released, otherwise they will be blown.

  • The adaptation class of B service is changed as follows:
public class MyServiceSentinelRequestOriginAdapter extends AbstractServiceSentinelRequestOriginAdapter {
    @Override
    public String parseOrigin(HttpServletRequest request) {
        String version = request.getHeader(DiscoveryConstant.N_D_SERVICE_VERSION);
        String userName = request.getHeader("userName");

        return version + "&" + userName;
    }
}
  • The authorization rules of B service are changed as follows:
[
    {
        "resource": "sentinel-resource",
        "limitApp": "1.0&zhangsan",
        "strategy": 0
    }
]

Sentinel gateway flow control practice

When we describe the practice of gateway flow control, we use the precise matching method to restrict the flow control of a service request as an example; we use the interface / inspector/inspect of the solar Service-A service of gateway agent as an example.

API Group Management

Add solar-service-a to API management page, and match string / inspector/inspect exactly

Gateway flow control rules

Configure related rules in the flow control rules interface

Finally, the output on Skywalking full link interface is as follows (similar to Sentinel buried point on Solar service side, which will not be described one by one):



Sentinel cluster current limiting practice

We adopt the embedded Token Server solution officially provided by Sentinel, that is, select a node in the service cluster as the Token Server, and the node also acts as the server that Token Client responds to external requests. The specific implementation method is to implement the reserved SPI InitFunc interface through Sentinel. Please refer to Sentinel demo cluster embedded under the official Sentinel demo module.

public class SentinelApolloTokenClusterInitFunc implements InitFunc {
    @Override
    public void init() throws Exception {
        // Register client dynamic rule data source.
        initDynamicFlowRuleProperty();
        initDynamicParamRuleProperty();

        // Register token client related data source.
        // Token client common config:
        ClusterClientConfigInitializer.doInit();

        // Token client assign config (e.g. target token server) retrieved from assign map:
        ClusterClientAssignConfigInitializer.doInit();

        // Register token server related data source.
        // Register dynamic rule data source supplier for token server:
        ClusterRuleSupplierInitializer.doInit();

        // Token server transport config extracted from assign map:
        ServerTransportConfigInitializer.doInit();

        // Init cluster state property for extracting mode from cluster map data source.
        ClusterStateInitializer.doInit();

        // ServerFlowConfig configuration
        ServerFlowConfigInitializer.doInit();
    }
}

Place the SPI extension pointcut class in the file \ resources\META-INF\services\com.alibaba.csp.sentinel.init.InitFunc, and the content is

com.zhangmen.solar.sentinel.SentinelApolloTokenClusterInitFunc

About the author

Ren Haojun, head of R & D Manager of infrastructure department. Worked for Ping An Bank, Wanda and HP, and was responsible for the research and development of PaaS platform infrastructure service framework of Ping An Bank platform architecture department. More than 10 years of open source experience, Github ID: @ HaojunRen, founder of Nepxion open source community, Nacos Group Member, spring cloud Alibaba & Nacos & sentinel & opentracking committer.

Zhang Binbin, head of infrastructure. Mainly responsible for the company's microservice architecture and the development and practice of open-source projects, open-source project enthusiasts, many years of Internet development experience.

Thank you very much for your support and help during the landing process.

Keywords: Java Spring InfluxDB Database SDK

Added by webtailor on Mon, 18 May 2020 09:32:34 +0300