项目中用到consul作为服务注册/发现、配置下发、负载均衡,保证了服务的高可用,最近简单学习了下它的原理。
关于consul的安装就不细说了,启几个server组成集群,再启俩个agent。
这里就有俩中方式注册服务:
1. 在启动agent的时候可以在consul的配置文件里直接注册服务
2. 也可以先不注册,之后服务通过http API向agent注册。
我们选的是第二种方式,这样agent不需要关注具体业务。
服务注册
要用到开源项目consul-clinet,文档上有使用案例 github地址
<dependencies>
<dependency>
<groupId>com.orbitz.consul</groupId>
<artifactId>consul-client</artifactId>
<version>0.16.3</version>
</dependency>
</dependencies>
import com.google.common.net.HostAndPort;
import com.orbitz.consul.AgentClient;
import com.orbitz.consul.Consul;
import com.orbitz.consul.HealthClient;
import com.orbitz.consul.model.health.ServiceHealth;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.List;
@RestController
public class ConsulController {
private static final String serviceName = "demo";
private static final String serviceTag = "dev";
private static final String host = "192.168.21.253";
private static final int port = 8804;
private static final String serviceId = host + port;
private Consul consul;
//注册服务名、tag和健康检查地址
@PostConstruct
public void consulInit() {
consul = Consul.builder().withHostAndPort(HostAndPort.fromParts("localhost", 8500)).build();
AgentClient agentClient = consul.agentClient();
try {
agentClient.register(port, URI.create("http://" + host + ":" + port + "/health").toURL(), 5L, serviceName, serviceId, serviceTag);
} catch (MalformedURLException e) {
e.printStackTrace();
}
System.out.println("consul init");
}
//获取健康的服务
@RequestMapping("/servicelist")
public String serviceList() {
HealthClient healthClient = consul.healthClient();
List<ServiceHealth> list = healthClient.getHealthyServiceInstances(serviceName).getResponse();
StringBuffer buffer = new StringBuffer();
for (ServiceHealth serviceHealth : list) {
String address = serviceHealth.getService().getAddress();
if (StringUtils.isEmpty(address)) {
address = serviceHealth.getNode().getAddress();
}
int port = serviceHealth.getService().getPort();
buffer.append(String.format("service (%s) address is (%s) port is (%d) \n", serviceName, address, port));
}
return buffer.toString();
}
}
这样就完成了服务的注册与发现,具体的发现规则,可以是随机、轮询、一致性哈希、哈希、权重。这个可以自己定义。