@@ -76,7 +76,7 @@ try { | |||
} | |||
``` | |||
So far the code modification is done. | |||
So far the code modification is done. We also provide [annotation support module](https://github.com/alibaba/Sentinel/blob/master/sentinel-extension/sentinel-annotation-aspectj/README.md) to define resource easier. | |||
### 3. Define Rules | |||
@@ -93,6 +93,8 @@ rules.add(rule); | |||
FlowRuleManager.loadRules(rules); | |||
``` | |||
For more information, please refer to [How To Use](https://github.com/alibaba/Sentinel/wiki/How-to-Use). | |||
### 4. Check the Result | |||
After running the demo for a while, you can see the following records in `~/logs/csp/${appName}-metrics.log`. | |||
@@ -144,3 +146,12 @@ These are only part of the companies using Sentinel, for reference only. If you | |||
![Taiping Renshou](http://www.cntaiping.com/tplresource/cms/www/taiping/img/home_new/tp_logo_img.png) | |||
![Shunfeng Technology](https://user-images.githubusercontent.com/9434884/48463502-2f48eb80-e817-11e8-984f-2f9b1b789e2d.png) | |||
![Mandao](https://user-images.githubusercontent.com/9434884/48463559-6cad7900-e817-11e8-87e4-42952b074837.png) | |||
![每日优鲜](https://home.missfresh.cn/statics/img/logo.png) | |||
![二维火](https://user-images.githubusercontent.com/9434884/49358468-bc43de00-f70d-11e8-97fe-0bf05865f29f.png) | |||
![文轩在线](http://static.winxuancdn.com/css/v2/images/logo.png) | |||
![客如云](https://www.keruyun.com/static/krynew/images/logo.png) | |||
![亲宝宝](https://stlib.qbb6.com/wclt/img/home_hd/version1/title_logo.png) | |||
![杭州光云科技](https://www.raycloud.com/images/logo.png) | |||
![金汇金融](https://res.jinhui365.com/r/images/logo2.png?v=1.527) | |||
![Vivo](https://user-images.githubusercontent.com/9434884/49355264-c6f87600-f701-11e8-8109-054cf91df868.png) | |||
![闪电购](http://cdn.52shangou.com/shandianbang/official-source/3.1.1/build/images/logo.png) |
@@ -46,17 +46,23 @@ import com.alibaba.csp.sentinel.util.StringUtil; | |||
*/ | |||
public class CommonFilter implements Filter { | |||
private final static String HTTP_METHOD_SPECIFY = "HTTP_METHOD_SPECIFY"; | |||
private final static String COLON = ":"; | |||
private boolean httpMethodSpecify = false; | |||
@Override | |||
public void init(FilterConfig filterConfig) { | |||
httpMethodSpecify = Boolean.parseBoolean(filterConfig.getInitParameter(HTTP_METHOD_SPECIFY)); | |||
} | |||
@Override | |||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | |||
throws IOException, ServletException { | |||
HttpServletRequest sRequest = (HttpServletRequest)request; | |||
throws IOException, ServletException { | |||
HttpServletRequest sRequest = (HttpServletRequest) request; | |||
Entry entry = null; | |||
Entry methodEntry = null; | |||
try { | |||
String target = FilterUtil.filterTarget(sRequest); | |||
// Clean and unify the URL. | |||
@@ -73,9 +79,16 @@ public class CommonFilter implements Filter { | |||
ContextUtil.enter(target, origin); | |||
entry = SphU.entry(target, EntryType.IN); | |||
// Add method specification if necessary | |||
if (httpMethodSpecify) { | |||
methodEntry = SphU.entry(sRequest.getMethod().toUpperCase() + COLON + target, | |||
EntryType.IN); | |||
} | |||
chain.doFilter(request, response); | |||
} catch (BlockException e) { | |||
HttpServletResponse sResponse = (HttpServletResponse)response; | |||
HttpServletResponse sResponse = (HttpServletResponse) response; | |||
// Return the block page, or redirect to another URL. | |||
WebCallbackManager.getUrlBlockHandler().blocked(sRequest, sResponse, e); | |||
} catch (IOException e2) { | |||
@@ -88,6 +101,9 @@ public class CommonFilter implements Filter { | |||
Tracer.trace(e4); | |||
throw e4; | |||
} finally { | |||
if (methodEntry != null) { | |||
methodEntry.exit(); | |||
} | |||
if (entry != null) { | |||
entry.exit(); | |||
} | |||
@@ -171,6 +171,6 @@ public class CommonFilterTest { | |||
@After | |||
public void cleanUp() { | |||
FlowRuleManager.loadRules(null); | |||
ClusterBuilderSlot.getClusterNodeMap().clear(); | |||
ClusterBuilderSlot.resetClusterNodes(); | |||
} | |||
} |
@@ -0,0 +1,133 @@ | |||
/* | |||
* Copyright 1999-2018 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.alibaba.csp.sentinel.adapter.servletmethod; | |||
import com.alibaba.csp.sentinel.adapter.servlet.config.WebServletConfig; | |||
import com.alibaba.csp.sentinel.adapter.servlet.util.FilterUtil; | |||
import com.alibaba.csp.sentinel.node.ClusterNode; | |||
import com.alibaba.csp.sentinel.slots.block.RuleConstant; | |||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; | |||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; | |||
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot; | |||
import com.alibaba.csp.sentinel.util.StringUtil; | |||
import org.junit.After; | |||
import org.junit.Test; | |||
import org.junit.runner.RunWith; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | |||
import org.springframework.boot.test.context.SpringBootTest; | |||
import org.springframework.http.MediaType; | |||
import org.springframework.test.context.junit4.SpringRunner; | |||
import org.springframework.test.web.servlet.MockMvc; | |||
import java.util.Collections; | |||
import static org.junit.Assert.*; | |||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | |||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; | |||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; | |||
/** | |||
* @author Roger Law | |||
*/ | |||
@RunWith(SpringRunner.class) | |||
@SpringBootTest(classes = TestApplication.class, | |||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) | |||
@AutoConfigureMockMvc | |||
public class CommonFilterMethodTest { | |||
private static final String HELLO_STR = "Hello!"; | |||
private static final String HELLO_POST_STR = "Hello Post!"; | |||
private static final String GET = "GET"; | |||
private static final String POST = "POST"; | |||
private static final String COLON = ":"; | |||
@Autowired | |||
private MockMvc mvc; | |||
private void configureRulesFor(String resource, int count) { | |||
configureRulesFor(resource, count, "default"); | |||
} | |||
private void configureRulesFor(String resource, int count, String limitApp) { | |||
FlowRule rule = new FlowRule() | |||
.setCount(count) | |||
.setGrade(RuleConstant.FLOW_GRADE_QPS); | |||
rule.setResource(resource); | |||
if (StringUtil.isNotBlank(limitApp)) { | |||
rule.setLimitApp(limitApp); | |||
} | |||
FlowRuleManager.loadRules(Collections.singletonList(rule)); | |||
} | |||
@Test | |||
public void testCommonFilterMiscellaneous() throws Exception { | |||
String url = "/hello"; | |||
this.mvc.perform(get(url)) | |||
.andExpect(status().isOk()) | |||
.andExpect(content().string(HELLO_STR)); | |||
ClusterNode cnGet = ClusterBuilderSlot.getClusterNode(GET + COLON + url); | |||
assertNotNull(cnGet); | |||
assertEquals(1, cnGet.passQps()); | |||
ClusterNode cnPost = ClusterBuilderSlot.getClusterNode(POST + COLON + url); | |||
assertNull(cnPost); | |||
this.mvc.perform(post(url)) | |||
.andExpect(status().isOk()) | |||
.andExpect(content().string(HELLO_POST_STR)); | |||
cnPost = ClusterBuilderSlot.getClusterNode(POST + COLON + url); | |||
assertNotNull(cnPost); | |||
assertEquals(1, cnPost.passQps()); | |||
testCommonBlockAndRedirectBlockPage(url, cnGet, cnPost); | |||
} | |||
private void testCommonBlockAndRedirectBlockPage(String url, ClusterNode cnGet, ClusterNode cnPost) throws Exception { | |||
configureRulesFor(GET + ":" + url, 0); | |||
// The request will be blocked and response is default block message. | |||
this.mvc.perform(get(url).accept(MediaType.TEXT_PLAIN)) | |||
.andExpect(status().isOk()) | |||
.andExpect(content().string(FilterUtil.DEFAULT_BLOCK_MSG)); | |||
assertEquals(1, cnGet.blockQps()); | |||
// Test for post pass | |||
this.mvc.perform(post(url)) | |||
.andExpect(status().isOk()) | |||
.andExpect(content().string(HELLO_POST_STR)); | |||
assertEquals(2, cnPost.passQps()); | |||
FlowRuleManager.loadRules(null); | |||
WebServletConfig.setBlockPage(""); | |||
} | |||
@After | |||
public void cleanUp() { | |||
FlowRuleManager.loadRules(null); | |||
ClusterBuilderSlot.resetClusterNodes(); | |||
} | |||
} |
@@ -0,0 +1,25 @@ | |||
package com.alibaba.csp.sentinel.adapter.servletmethod; | |||
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter; | |||
import org.springframework.boot.web.servlet.FilterRegistrationBean; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.Configuration; | |||
/** | |||
* @author: Roger Law | |||
**/ | |||
@Configuration | |||
public class FilterMethodConfig { | |||
@Bean | |||
public FilterRegistrationBean sentinelFilterRegistration() { | |||
FilterRegistrationBean registration = new FilterRegistrationBean(); | |||
registration.setFilter(new CommonFilter()); | |||
registration.addUrlPatterns("/*"); | |||
registration.addInitParameter("HTTP_METHOD_SPECIFY", "true"); | |||
registration.setName("sentinelFilter"); | |||
registration.setOrder(1); | |||
return registration; | |||
} | |||
} |
@@ -0,0 +1,30 @@ | |||
/* | |||
* Copyright 1999-2018 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.alibaba.csp.sentinel.adapter.servletmethod; | |||
import org.springframework.boot.SpringApplication; | |||
import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
/** | |||
* @author Eric Zhao | |||
*/ | |||
@SpringBootApplication | |||
public class TestApplication { | |||
public static void main(String[] args) { | |||
SpringApplication.run(TestApplication.class, args); | |||
} | |||
} |
@@ -0,0 +1,38 @@ | |||
/* | |||
* Copyright 1999-2018 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.alibaba.csp.sentinel.adapter.servletmethod; | |||
import org.springframework.web.bind.annotation.GetMapping; | |||
import org.springframework.web.bind.annotation.PostMapping; | |||
import org.springframework.web.bind.annotation.RestController; | |||
/** | |||
* @author Roger Law | |||
*/ | |||
@RestController | |||
public class TestMethodController { | |||
@GetMapping("/hello") | |||
public String apiHello() { | |||
return "Hello!"; | |||
} | |||
@PostMapping("/hello") | |||
public String apiHelloPost() { | |||
return "Hello Post!"; | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
/* | |||
* Copyright 1999-2018 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.alibaba.csp.sentinel.cluster; | |||
/** | |||
* Token client interface for distributed flow control. | |||
* | |||
* @author Eric Zhao | |||
* @since 1.4.0 | |||
*/ | |||
public interface ClusterTokenClient extends TokenService { | |||
/** | |||
* Get descriptor of current token server. | |||
* | |||
* @return current token server | |||
*/ | |||
TokenServerDescriptor currentServer(); | |||
} |
@@ -0,0 +1,61 @@ | |||
/* | |||
* Copyright 1999-2018 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.alibaba.csp.sentinel.cluster; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.ServiceLoader; | |||
import com.alibaba.csp.sentinel.log.RecordLog; | |||
/** | |||
* Provider for a universal {@link ClusterTokenClient} instance. | |||
* | |||
* @author Eric Zhao | |||
* @since 1.4.0 | |||
*/ | |||
public final class TokenClientProvider { | |||
private static ClusterTokenClient client = null; | |||
private static final ServiceLoader<ClusterTokenClient> LOADER = ServiceLoader.load(ClusterTokenClient.class); | |||
static { | |||
// Not strictly thread-safe, but it's OK since it will be resolved only once. | |||
resolveTokenClientInstance(); | |||
} | |||
public static ClusterTokenClient getClient() { | |||
return client; | |||
} | |||
private static void resolveTokenClientInstance() { | |||
List<ClusterTokenClient> clients = new ArrayList<ClusterTokenClient>(); | |||
for (ClusterTokenClient client : LOADER) { | |||
clients.add(client); | |||
} | |||
if (!clients.isEmpty()) { | |||
// Get first. | |||
client = clients.get(0); | |||
RecordLog.info("[TokenClientProvider] Token client resolved: " + client.getClass().getCanonicalName()); | |||
} else { | |||
RecordLog.warn("[TokenClientProvider] No existing token client, resolve failed"); | |||
} | |||
} | |||
private TokenClientProvider() {} | |||
} |
@@ -0,0 +1,59 @@ | |||
/* | |||
* Copyright 1999-2018 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.alibaba.csp.sentinel.cluster.log; | |||
import java.io.File; | |||
import com.alibaba.csp.sentinel.eagleeye.EagleEye; | |||
import com.alibaba.csp.sentinel.eagleeye.StatLogger; | |||
import com.alibaba.csp.sentinel.log.LogBase; | |||
/** | |||
* @author jialiang.linjl | |||
* @author Eric Zhao | |||
* @since 1.4.0 | |||
*/ | |||
public final class ClusterStatLogUtil { | |||
private static final String FILE_NAME = "sentinel-cluster.log"; | |||
private static StatLogger statLogger; | |||
static { | |||
String path = LogBase.getLogBaseDir() + FILE_NAME; | |||
statLogger = EagleEye.statLoggerBuilder("sentinel-cluster-record") | |||
.intervalSeconds(1) | |||
.entryDelimiter('|') | |||
.keyDelimiter(',') | |||
.valueDelimiter(',') | |||
.maxEntryCount(5000) | |||
.configLogFilePath(path) | |||
.maxFileSizeMB(300) | |||
.maxBackupIndex(3) | |||
.buildSingleton(); | |||
} | |||
public static void log(String msg) { | |||
statLogger.stat(msg).count(); | |||
} | |||
public static void log(String msg, int count) { | |||
statLogger.stat(msg).count(count); | |||
} | |||
private ClusterStatLogUtil() {} | |||
} |
@@ -26,6 +26,7 @@ import com.alibaba.csp.sentinel.node.metric.MetricNode; | |||
* @author qinan.qn | |||
* @author leyou | |||
* @author Eric Zhao | |||
* @author leitao | |||
*/ | |||
public interface Node { | |||
@@ -147,7 +148,7 @@ public interface Node { | |||
void increaseThreadNum(); | |||
/** | |||
* Increase current thread count. | |||
* Decrease current thread count. | |||
*/ | |||
void decreaseThreadNum(); | |||
@@ -68,7 +68,7 @@ app.controller('MetricCtl', ['$scope', '$stateParams', 'MetricService', '$interv | |||
forceFit: true, | |||
width: 100, | |||
height: 250, | |||
padding: [10, 30, 70, 30] | |||
padding: [10, 30, 70, 50] | |||
}); | |||
var maxQps = 0; | |||
for (var i in metric.data) { | |||
@@ -33,16 +33,14 @@ angular.module('sentinelDashboardApp') | |||
// toggle side bar | |||
$scope.click = function ($event) { | |||
let element = angular.element($event.target); | |||
let entry = angular.element($event.target).scope().entry; | |||
entry.active = !entry.active; | |||
entry.active = !entry.active;// toggle this clicked app bar | |||
if (entry.active === false) { | |||
element.parent().children('ul').hide(); | |||
} else { | |||
element.parent().parent().children('li').children('ul').hide(); | |||
element.parent().children('ul').show(); | |||
} | |||
$scope.apps.forEach(function (item) {// collapse other app bars | |||
if (item != entry) { | |||
item.active = false; | |||
} | |||
}); | |||
}; | |||
/** | |||
@@ -16,6 +16,8 @@ | |||
package com.alibaba.csp.sentinel.transport.config; | |||
import com.alibaba.csp.sentinel.config.SentinelConfig; | |||
import com.alibaba.csp.sentinel.util.HostNameUtil; | |||
import com.alibaba.csp.sentinel.util.StringUtil; | |||
/** | |||
* @author leyou | |||
@@ -25,6 +27,7 @@ public class TransportConfig { | |||
public static final String CONSOLE_SERVER = "csp.sentinel.dashboard.server"; | |||
public static final String SERVER_PORT = "csp.sentinel.api.port"; | |||
public static final String HEARTBEAT_INTERVAL_MS = "csp.sentinel.heartbeat.interval.ms"; | |||
public static final String HEARTBEAT_CLIENT_IP = "csp.sentinel.heartbeat.client.ip"; | |||
private static int runtimePort = -1; | |||
@@ -66,4 +69,18 @@ public class TransportConfig { | |||
public static void setRuntimePort(int port) { | |||
runtimePort = port; | |||
} | |||
/** | |||
* Get heartbeat client local ip. | |||
* If the client ip not configured,it will be the address of local host | |||
* | |||
* @return the local ip. | |||
*/ | |||
public static String getHeartbeatClientIp() { | |||
String ip = SentinelConfig.getConfig(HEARTBEAT_CLIENT_IP); | |||
if (StringUtil.isBlank(ip)) { | |||
ip = HostNameUtil.getIp(); | |||
} | |||
return ip; | |||
} | |||
} |
@@ -0,0 +1,25 @@ | |||
package com.alibaba.csp.sentinel.transport.config; | |||
import com.alibaba.csp.sentinel.config.SentinelConfig; | |||
import org.junit.Test; | |||
import static org.junit.Assert.*; | |||
public class TransportConfigTest { | |||
@Test | |||
public void getClientIp() { | |||
//config heartbeat client ip | |||
System.setProperty(TransportConfig.HEARTBEAT_CLIENT_IP, "10.10.10.10"); | |||
String ip = TransportConfig.getHeartbeatClientIp(); | |||
assertNotNull(ip); | |||
assertEquals(ip, "10.10.10.10"); | |||
//no heartbeat client ip | |||
SentinelConfig.setConfig(TransportConfig.HEARTBEAT_CLIENT_IP, ""); | |||
ip = TransportConfig.getHeartbeatClientIp(); | |||
assertNotNull(ip); | |||
} | |||
} |
@@ -85,7 +85,7 @@ public class HttpHeartbeatSender implements HeartbeatSender { | |||
.setParameter("v", Constants.SENTINEL_VERSION) | |||
.setParameter("version", String.valueOf(System.currentTimeMillis())) | |||
.setParameter("hostname", HostNameUtil.getHostName()) | |||
.setParameter("ip", HostNameUtil.getIp()) | |||
.setParameter("ip", TransportConfig.getHeartbeatClientIp()) | |||
.setParameter("port", TransportConfig.getPort()) | |||
.setParameter("pid", String.valueOf(PidUtil.getPid())); | |||
@@ -19,11 +19,11 @@ import java.io.IOException; | |||
import java.net.ServerSocket; | |||
import java.net.Socket; | |||
import java.net.SocketException; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import java.util.Map.Entry; | |||
import java.util.Set; | |||
import java.util.concurrent.ArrayBlockingQueue; | |||
import java.util.concurrent.ConcurrentHashMap; | |||
import java.util.concurrent.ExecutorService; | |||
import java.util.concurrent.Executors; | |||
import java.util.concurrent.RejectedExecutionException; | |||
@@ -53,7 +53,7 @@ public class SimpleHttpCommandCenter implements CommandCenter { | |||
private static final int DEFAULT_PORT = 8719; | |||
@SuppressWarnings("rawtypes") | |||
private static final Map<String, CommandHandler> handlerMap = new HashMap<String, CommandHandler>(); | |||
private static final Map<String, CommandHandler> handlerMap = new ConcurrentHashMap<String, CommandHandler>(); | |||
private ExecutorService executor = Executors.newSingleThreadExecutor( | |||
new NamedThreadFactory("sentinel-command-center-executor")); | |||
@@ -105,12 +105,14 @@ public class SimpleHttpCommandCenter implements CommandCenter { | |||
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(); | |||
} | |||
@@ -119,11 +121,11 @@ public class SimpleHttpCommandCenter implements CommandCenter { | |||
new Thread(serverInitTask).start(); | |||
} | |||
/** | |||
* Get a server socket from an available port from a base port.<br> | |||
* Increasing on port number will occur when the port has already been used. | |||
* | |||
* | |||
* @param basePort base port to start | |||
* @return new socket with available port | |||
*/ | |||
@@ -135,7 +137,7 @@ public class SimpleHttpCommandCenter implements CommandCenter { | |||
server.setReuseAddress(true); | |||
return server; | |||
} catch (IOException e) { | |||
tryCount ++; | |||
tryCount++; | |||
try { | |||
TimeUnit.MILLISECONDS.sleep(30); | |||
} catch (InterruptedException e1) { | |||
@@ -36,7 +36,7 @@ public class HeartbeatMessage { | |||
public HeartbeatMessage() { | |||
message.put("hostname", HostNameUtil.getHostName()); | |||
message.put("ip", HostNameUtil.getIp()); | |||
message.put("ip", TransportConfig.getHeartbeatClientIp()); | |||
message.put("app", AppNameUtil.getAppName()); | |||
message.put("port", String.valueOf(TransportConfig.getPort())); | |||
} | |||