这也不是一篇非常详细的源码领读,源码细节还需你自己仔细咀嚼

这只是我在改了些sentinel bug后,梳理的脉络,主要是脉络。看完后对Sentinel的源码模块划分和大致交互有个整体印象。

从而在想知道细节时知道从哪里下手。

Sentinel功能强大,但是开源出来的sentinel可以说是一个半成品,bug多,并且很多功能没有实现,可能是因为它有收费的版本吧。因此我们如果想在生产上应用就要戒骄戒躁,了解它的源码,对它进行优化改造。在改造过程中不可避免的要调用sentinel的api接口进行一些规则的同步等操作。

监听端口

服务集成sentinel的方式

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

启动服务后,一旦访问了接口,sentinel会通过websocket或netty的方式监听8719(默认)端口,提供一些接口方便我们以http的方式调用取获取、修改sentinel的限流规则,集群配置等。

监听的端口默认是8719,但是如果端口被占用,就会换自动换端口,具体换端口逻辑是8719+重试次数/3,这个没什么意思,不比深究。

代码实现

具体启动端口监听的逻辑在com.alibaba.csp.sentinel.transport.init.CommandCenterInitFunc中,该类在sentinel-transport-common模块中,具体依赖如下

 

@InitOrder(-1)
public class CommandCenterInitFunc implements InitFunc {

    @Override
    public void init() throws Exception {
        //commandCenter默认是SimpleHttpCommandCenter
        CommandCenter commandCenter = CommandCenterProvider.getCommandCenter();

        if (commandCenter == null) {
            RecordLog.warn("[CommandCenterInitFunc] Cannot resolve CommandCenter");
            return;
        }

        commandCenter.beforeStart();
        //启动监听
        commandCenter.start();
        RecordLog.info("[CommandCenterInit] Starting command center: "
                + commandCenter.getClass().getCanonicalName());
    }
}

上述代码中commandCenter默认是SimpleHttpCommandCenter,如果引入sentinel-transport-netty-http,则它就会变成NettyHttpCommandCenter,具体原因是sentinel为spi类定义了一个order属性,NettyHttpCommandCenter的order属性更高

 

 

具体模块之间的关系如下如

 

端口可通过参数:csp.sentinel.api.port指定。

具体启动逻辑可以自己跟一下,比较简单。

api接口

具体有哪些接口呢?

com.alibaba.csp.sentinel.command.CommandHandler接口的所有实现类

我们可以通过调用localhost:port/api获取到所有的api

 

这些handler基本上分布在三个模块中

  • sentinel-transport-common:提供一些规则相关的,基本的接口
  • sentinel-cluster-client-default:集群客户端相关接口
  • sentinel-cluster-server-default:集群服务端相关接口

sentinel-transport-common

ApiCommandHandler /api 获取所有接口
FetchClusterModeCommandHandler /getClusterMode 获取集群模式信息
ModifyClusterModeCommandHandler /setClusterMode 修改集群模式
BasicInfoCommandHandler /basicInfo 获取服务基本信息
FetchActiveRuleCommandHandler /getRules 获取规则,参数type flow|degrade|authority|system
FetchClusterNodeByIdCommandHandler /clusterNodeById 根据id查询clustNode信息
FetchClusterNodeHumanCommandHandler /cnode get clusterNode metrics by id, request param: id=
FetchJsonTreeCommandHandler /jsonTree 簇点链路
FetchOriginCommandHandler /origin get origin clusterNode by id, request param: id=
FetchSimpleClusterNodeCommandHandler /clusterNode get all clusterNode VO, use type=notZero to ignore those nodes with totalRequest <=0
FetchSystemStatusCommandHandler /systemStatus get system status
FetchTreeCommandHandler /tree get metrics in tree mode, use id to specify detailed tree root 统计信息
ModifyRulesCommandHandler /setRules 更新规则
OnOffGetCommandHandler /getSwitch get sentinel switch status
OnOffSetCommandHandler /setSwitch set sentinel switch, accept param: value=
SendMetricCommandHandler /metric get and aggregate metrics, accept param:startTime={startTime}&endTime={endTime}&maxLines={maxLines}&identify=
VersionCommandHandler /version sentinel版本 1.8.1

sentinel-cluster-client-default

FetchClusterClientConfigHandler /cluster/client/fetchConfig 获取集群-客户端配置
ModifyClusterClientConfigHandler /cluster/client/modifyConfig 修改集群-客户端配置

sentinel-cluster-server-default

FetchClusterFlowRulesCommandHandler /cluster/server/flowRules 获取集群限流规则
FetchClusterParamFlowRulesCommandHandler /cluster/server/paramRules 获取集群热点参数规则
FetchClusterServerConfigHandler /cluster/server/fetchConfig 获取集群server配置
FetchClusterServerInfoCommandHandler /cluster/server/info 获取集群server信息
FetchClusterMetricCommandHandler /cluster/server/metricList 获取集群统计信息
ModifyClusterFlowRulesCommandHandler /cluster/server/modifyFlowRules 修改集群限流规则
ModifyClusterParamFlowRulesCommandHandler /cluster/server/modifyParamRules 修改集群热点参数规则
ModifyClusterServerFlowConfigHandler /cluster/server/modifyFlowConfig 待查看
ModifyClusterServerTransportConfigHandler /cluster/server/modifyTransportConfig 修改集群server配置
ModifyServerNamespaceSetHandler /cluster/server/modifyNamespaceSet 修改namespace信息

 

public class SimpleHttpCommandCenter implements CommandCenter {

public void run() {
    boolean success = false;
    ServerSocket serverSocket = SimpleHttpCommandCenter.getServerSocketFromBasePort(this.port);
    if (serverSocket != null) {
        CommandCenterLog.info("[CommandCenter] Begin listening at port " + serverSocket.getLocalPort(), new Object[0]);
        SimpleHttpCommandCenter.this.socketReference = serverSocket;
        SimpleHttpCommandCenter.this.executor.submit(SimpleHttpCommandCenter.this.new ServerThread(serverSocket));
        success = true;
        this.port = serverSocket.getLocalPort();
    } else {
        CommandCenterLog.info("[CommandCenter] chooses port fail, http command center will not work", new Object[0]);
    }

    if (!success) {
        this.port = -1;
    }

    TransportConfig.setRuntimePort(this.port);
    SimpleHttpCommandCenter.this.executor.shutdown();
}
}

项目集成sentinel启动后,api服务并不会启动,而是等到项目被访问的时候才会被启动,具体的方式是启动一个netty服务监听8719端口(默认)

SphU.entry("testRule1", EntryType.IN, 1, id);