consul
consul的理论概念自行百度一下,此处不再叙述
1. consul的搭建
此处我们使用docker
来搭建consul的集群,至于docker不是很熟练的同学,自行恶补一下
1.1 docker拉取consul
拉取的命令很简单
docker pull consul
默认下载最新的consul镜像文件,下载完成好之后我们开始启动一个节点,作为集群的一个节点,这里我们搭建三个节点,最终组装成一个集群,因我这里只有一台机器,所以我们部署在一台机器上,分别采用三个端口,这样就是三个节点,实际使用过程中,一般都是三台机器来搭建三个节点。
1.2 搭建第一个节点
执行的命令为:
docker run --name consul1 -d -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8600:8600 consul:1.2.2 agent -server -bootstrap-expect 2 -ui -bind=0.0.0.0 -client=0.0.0.0
至于里面所使用的命令下面简单介绍一下
–net=host docker参数, 使得docker容器越过了net namespace的隔离,免去手动指定端口映射的步骤
-server consul支持以server或client的模式运行, server是服务发现模块的核心, client主要用于转发请求
-advertise 将本机私有IP传递到consul
-retry-join 指定要加入的consul节点地址,失败后会重试, 可多次指定不同的地址
-client 指定consul绑定在哪个client地址上,这个地址可提供HTTP、DNS、RPC等服务,默认是>127.0.0.1
-bind 绑定服务器的ip地址;该地址用来在集群内部的通讯,集群内的所有节点到地址必须是可达的,>默认是0.0.0.0
allow_stale 设置为true则表明可从consul集群的任一server节点获取dns信息, false则表明每次请求都会>经过consul的server leader
-bootstrap-expect 数据中心中预期的服务器数。指定后,Consul将等待指定数量的服务器可用,然后>启动群集。允许自动选举leader,但不能与传统-bootstrap标志一起使用, 需要在server模式下运行。
-data-dir 数据存放的位置,用于持久化保存集群状态
-node 群集中此节点的名称,这在群集中必须是唯一的,默认情况下是节点的主机名。
-config-dir 指定配置文件,当这个目录下有 .json 结尾的文件就会被加载,详细可参考https://www.consul.io/docs/agent/options.html#configuration_files
-enable-script-checks 检查服务是否处于活动状态,类似开启心跳
-datacenter 数据中心名称
-ui 开启ui界面
-join 指定ip, 加入到已有的集群中
1.3 查看第一个节点的地址
执行如下的命令我们来查看第一个节点的地址,这个很重要,因为我们要给节点二和节点三绑定到节点一上。
docker inspect --format ‘{{ .NetworkSettings.IPAddress }}‘ consul1
1.4 搭建第二个节点
执行命令:
docker run --name consul3 -d -p 8501:8500 consul agent -server -ui -bind=0.0.0.0 -client=0.0.0.0 -join 172.17.0.2
1.5 搭建第三个节点
执行命令:
docker run --name consul3 -d -p 8502:8500 consul agent -server -ui -bind=0.0.0.0 -client=0.0.0.0 -join 172.17.0.2
搭建完成之后,我们查看docker容器运行的情况,查看运行状态
我们可以看到我们新建的consul集群已经在运行中,我这里是将防火墙关闭了,我们你是启动的防火墙,要是访问我们需要做个防火墙开放端口,开放端口之后,并且重启防火墙。完了才可以执行下面的操作。
1.6 查看集群
通过浏览器访问192.168.1.100:8500之后,如果能看到下面的界面,说明我们的集群搭建完成了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
继续访问节点2 节点2我们的端口是8501
访问节点3 端口是8502
至此我们consul的集群算是搭建完毕了。那我们如何使用它呢?
2. 调用consul
2.1 新建一个服务提供者
新建一个项目名称叫consul-provider,引入如下图所示的
2.2 修改服务提供者配置文件
我们在新建的服务提供者的配置文件中加入如下配置:
spring.application.name=consul-provider
server.port=3000
spring.cloud.consul.host=192.168.1.100
spring.cloud.consul.port=8500
spring.cloud.consul.discovery.service-name=consul-provider
注意:
spring.cloud.consul.host
中配置的是我们consul的地址,spring.cloud.consul.port
中配置的是我们consul的端口,此处我们只配置三个节点中的任意一个,我们我们新建的三个节点,本身是带有复制功能,所以随便配置一个,其他两个都能获取到这个服务提供者。这里和zk的用法不太一样。
2.3 服务提供者业务
为了演示我们给服务提供者集群部署,测试一下负载均衡。
我们新建一个controller,内容如下:
完了我们开启注册服务,在启动类上加上注解@EnableDiscoveryClient
完成以上配置之后,我们需要打包,完了集群部署。
2.4 集群部署服务提供者
右击服务提供者的target,选择open in terminal
之后执行命令
java -jar consul-provider-0.0.1-SNAPSHOT.jar --server.port=3001
再次右击服务提供者的target,选择open in terminal,执行命令
java -jar consul-provider-0.0.1-SNAPSHOT.jar --server.port=3002
我们访问consul,查看服务注册情况。
我们先访问节点1,查看运行情况。
再访问节点2
最后访问节点3
我们可以看出来 我们注册的时候配置文件的地址只写了一个节点的地址,但是我们同样可以看到节点2和节点3的运行情况,完全和节点1一样。
2.5 新建服务消费者
和新建服务提供者是一样的。引入这三个jar包
2.6 修改服务消费者的配置文件
这里修改的配置文件和服务提供者的一样,如下图所示:
spring.application.name=consul-consumer
server.port=3100
spring.cloud.consul.host=192.168.1.100
spring.cloud.consul.port=8500
spring.cloud.consul.discovery.service-name=consul-consumer
2.7 修改服务消费者的启动类
因为我们这里需要调用服务提供者,所以我们需要新建一个restTemplate
@SpringBootApplication
@EnableDiscoveryClient
public class ConsulConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsulConsumerApplication.class, args);
}
@Bean
// @LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
注意:这里的restTemplate可以采用轮询,也可以不用再这里设置轮询,我们再具体代码调用的地方再设置
2.8 服务消费者的业务编写
新建一个controller,编写一个简单的参数接受并返回的方法。
@RestController
public class ConsulConsumerController {
@Autowired
RestTemplate restTemplate;
@Autowired
LoadBalancerClient loadBalancerClient;
@GetMapping("/consulconsumer")
public String hello(){
ServiceInstance choose = loadBalancerClient.choose("consul-provider");
URI uri = choose.getUri();
String forObject = restTemplate.getForObject(uri + "/consulprovider?name={1}", String.class,"muyan");
return forObject;
}
}
上面就是就是再controller中采用的轮询方式,如果我们在启动类的RestTemplate中加上@LoadBalanced,那么此处的代码应该是:
@RestController
public class ConsulConsumerController {
@Autowired
RestTemplate restTemplate;
@Autowired
LoadBalancerClient loadBalancerClient;
@GetMapping("/consulconsumer")
public String hello(){
// ServiceInstance choose = loadBalancerClient.choose("consul-provider");
// URI uri = choose.getUri();
String forObject = restTemplate.getForObject("http://consul-provider/consulprovider?name={1}", String.class, "mumu");
// String forObject = restTemplate.getForObject(uri + "/consulprovider?name={1}", String.class,"muyan");
return forObject;
}
}
切记,千万不要在启动类上加上了@LoadBalanced注解之后,再在controller中采用LoadBalancerClient的choose方式来调用远程服务,因为serverid必须是我们访问的服务名称 ,当我们直接输入ip的时候获取的server是null,就会抛出异常。
2.9 测试
启动服务消费者。我们通过浏览器来调用consulconsumer方法。
可以看到调用的3001端口的服务提供者,我们再刷新
我们可以看到出现的调用时3002的端口服务提供者。