标签:问题 ctc 外网地址 href 自动提交 效果图 rri autowired property
开源生态
Sentinel 分为两个部分:
根据该步骤,建立demo
控制台效果图
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.6.2</version>
</dependency>
定义资源:也就是对哪个资源进行流量控制,现在已经提供了注解形式,所以新的接入直接用注解,@SentinelResource
由于我的系统使用的是apollo管理配置,所以我用apollo来管理规则,官方也提供了apollo的接入说明,然后我想到需要自动提交规则,而不是自己手动去配,又找到了官方的推送例子,可是该例子还是存在问题的,或者说要运行该例子需要对apollo的开放设置有进一步了解
期间我遇到了401问题,是因为需要apollo授权第三方应用,配置token后才能起效;
之后又遇到400问题,是因为openItemDTO.setDataChangeCreatedBy("apollo");
和namespaceReleaseDTO.setReleasedBy("apollo");
该配置项,例子并不是这么写的,需要将参数改成apollo才行
下面给出完整配置,结合apollo读取配置
@Configuration
public class SentinelAspectConfiguration {
@Autowired
private ApolloOpenApiClient apolloOpenApiClient;
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
pushlish();
return new SentinelResourceAspect();
}
private void pushlish(){
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("GET-CreditPointsPercent");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// Set limit QPS to 20.
rule.setCount(5);
rules.add(rule);
// Increase the configuration
String appId = "carer01";
String flowDataId = appId+"-flow-rules";
OpenItemDTO openItemDTO = new OpenItemDTO();
openItemDTO.setKey(flowDataId);
openItemDTO.setValue(JSON.toJSONString(rules));
openItemDTO.setComment("Program auto-join");
openItemDTO.setDataChangeCreatedBy("apollo");
apolloOpenApiClient.createOrUpdateItem(appId, "DEV", "default", "application", openItemDTO);
// Release configuration
NamespaceReleaseDTO namespaceReleaseDTO = new NamespaceReleaseDTO();
namespaceReleaseDTO.setEmergencyPublish(true);
namespaceReleaseDTO.setReleaseComment("Modify or add configurations");
namespaceReleaseDTO.setReleasedBy("apollo");
namespaceReleaseDTO.setReleaseTitle("Modify or add configurations");
apolloOpenApiClient.publishNamespace(appId, "DEV", "default", "application", namespaceReleaseDTO);
String namespaceName = "application";
String defaultFlowRules = "[]";
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ApolloDataSource<>(namespaceName,
flowDataId, defaultFlowRules, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
}));
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
}
}
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
登录名密码都是sentinel
2019-07-23 14:57:33.256 ERROR 14788 --- [pool-2-thread-1] c.a.c.s.dashboard.metric.MetricFetcher : Failed to fetch metric from <http://172.16.100.141:8721/metric?startTime=1563865044000&endTime=1563865050000&refetch=false> (ConnectionException: Connection refused: no further information)
说明发送了内网地址,导致fetch拉取埋点信息不通
我通过System.setProperty(TransportConfig.HEARTBEAT_CLIENT_IP, split[0].trim());
设置心跳地址为外网地址解决这个问题
本质上是因为控制台主动通过接口来客户端拉信息,但若是访问不通,也是没辙,所以本地测试部在服务器上的控制台,除非外网映射
我的这个问题基础是因为我部署到docker上的,之后debug源码,发现控制台调用客户端的地址是我根本没配过的,深入后发现如下代码段
Runnable serverInitTask = new Runnable() {
int port;
{
try {
port = Integer.parseInt(TransportConfig.getPort());
} catch (Exception e) {
port = DEFAULT_PORT;
}
}
@Override
public void run() {
boolean success = false;
ServerSocket serverSocket = getServerSocketFromBasePort(port);
if (serverSocket != null) {
CommandCenterLog.info("[CommandCenter] Begin listening at port " + serverSocket.getLocalPort());
socketReference = serverSocket;
executor.submit(new ServerThread(serverSocket));
success = true;
port = serverSocket.getLocalPort();
} else {
CommandCenterLog.info("[CommandCenter] chooses port fail, http command center will not work");
}
if (!success) {
port = PORT_UNINITIALIZED;
}
TransportConfig.setRuntimePort(port);
executor.shutdown();
}
};
new Thread(serverInitTask).start();
该代码段的作用是为客户端在分配一个socketServer,之后的信息交互都是通过该服务提供的端口来提供;
这样一来客户端需要额外提供一个端口了,而我的docker只暴露了1个服务端口,所以不可避免的会出现问题,以上是我到目前的思路,正在验证中
至于端口如何决定,它是用了一个简单的技巧,若设置了csp.sentinel.api.port
配置项,则会取该配置端口,若没有设,则是默认端口8719;但如果你用的是官网的启动方式,那8719应该是被控制台占用了,所以进入小技巧getServerSocketFromBasePort
方法,内容如下
private static ServerSocket getServerSocketFromBasePort(int basePort) {
int tryCount = 0;
while (true) {
try {
ServerSocket server = new ServerSocket(basePort + tryCount / 3, 100);
server.setReuseAddress(true);
return server;
} catch (IOException e) {
tryCount++;
try {
TimeUnit.MILLISECONDS.sleep(30);
} catch (InterruptedException e1) {
break;
}
}
}
return null;
}
它会循环尝试端口是否被占用,每个端口尝试三次,若被占用则取下一个+1端口,一直到可用的端口返回;所以如果我们的客户端应用放到了docker,而开放的端口只有一个,那就获取不了信息了
这里csp.sentinel.api.port
配置项很容易理解成客户端的端口地址,因为启动也不会报错啥的,会误让我们误会这个参数可以不填,虽然文档上写着必填,但本地测试的时候可没影响-_-||,所有都注意了,这个配置项是必填的
标签:问题 ctc 外网地址 href 自动提交 效果图 rri autowired property
原文地址:https://www.cnblogs.com/sky-chen/p/11237133.html