运行环境:
Windows 10 专业版
Docker for Windows 18.06.0-ce(安装方法参见win10环境下安装Docker)
主要参考文章《springcloud(十三):Eureka 2.X 停止开发,但注册中心还有更多选择:Consul 使用详解》
Consul是什么,为什么用Consul,请大家看上面提到的Consul使用详解或百度。这里列出一些我试出来或理解的一些东西。
docker pull consul
docker images
注意:带”$(“这种命令的操作必须在PowerShell下执行。
docker run -d -h node1 --name node1 -p 8501:8500 consul agent -server -bootstrap-expect=3 -client 0.0.0.0 -ui
$JOIN_IP="$(docker inspect -f '{{.NetworkSettings.IPAddress}}' node1)"
docker run -d -h node2 --name node2 -p 8502:8500 consul agent -server -join $JOIN_IP -client 0.0.0.0 -ui
docker run -d -h node3 --name node3 -p 8503:8500 consul agent -server -join $JOIN_IP -client 0.0.0.0 -ui
docker run -d -h node4 --name node4 -p 8504:8500 consul agent -server -join $JOIN_IP -client 0.0.0.0 -ui
docker run -d -h node5 --name node5 -p 8505:8500 consul agent -server -join $JOIN_IP -client 0.0.0.0 -ui
docker run -d -h node6 --name node6 -p 8506:8500 consul agent -join $JOIN_IP -client 0.0.0.0 -ui
docker exec node1 consul members
-d:在后台运行
-h:容器的主机名(也就是consul节点的名字)
–name:容器名称(可以指定名字删除容器)
-p:把容器内的端口映射到宿主机(我们可以把每个节点的端口都映射出来)
-server:作为server节点(node6没加这参数就是client节点)
-bootstrap-expect=3:至少3个server节点才算正常的集群
-client 0.0.0.0:表示接受任何客户端连接
-ui:能访问web管理页面(-p和-client也必须设好)
JOIN_IP:把node1的ip地址设为变量(cmd不支持,必须PowerShell)
-join $JOIN_IP:把节点加入到某个IP,组成集群(新的节点只要加到已有集群中任何一个IP都行)
docker exec node1 consul members:运行node1(随便哪个)的consul members命令,查看集群情况
docker run -d -h node21 --name node21 -p 8521:8500 consul agent -server -bootstrap-expect=3 -client 0.0.0.0 -ui -datacenter=dc2
$JOIN_IP="$(docker inspect -f '{{.NetworkSettings.IPAddress}}' node21)"
docker run -d -h node22 --name node22 consul agent -server -datacenter=dc2 -join $JOIN_IP
docker run -d -h node23 --name node23 consul agent -server -datacenter=dc2 -join $JOIN_IP
docker run -d -h node24 --name node24 consul agent -datacenter=dc2 -join $JOIN_IP
docker exec node21 consul members
-datacenter=dc2:当前节点的数据中心设为dc2(默认是dc1)
后面3个节点都加入node21组成了集群(必须同数据中心才能组成集群)
docker exec node1 consul join -wan $JOIN_IP
docker exec node1 consul members -wan
node1:数据中心dc1任一节点
JOIN_IP:数据中心dc2任一节点的IP
join -wan:两个数据中心建立关联
members -wan:查看广域网集群情况(两个数据中心的server节点组成了广域网集群)
http://localhost:8501/ui/dc2/services
8501可以是前面映射出来的任一个ip,能看到同样的效果,说明集群创建成功了。
如果容器创建失败或不想要了,可以删除某个或全部容器。
docker stop node1
docker rm node1
docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.cloud:spring-cloud-starter')
compile('org.springframework.cloud:spring-cloud-starter-consul-discovery')
}
6.完善server代码
ConsulServerApplication.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient //表示支持服务发现
public class ConsulServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsulServerApplication.class, args);
}
}
application.yml
spring:
cloud:
consul:
host: 127.0.0.1
port: 8502
discovery:
instance-id: consul-server1
serviceName: consul-server
hostname: 192.168.3.115
application:
name: spring-cloud-consul-server
server:
port: 8511
consul:server因为已经映射出来,所以就是本机IP(别的电脑想连你的consul就要用你的局域网IP)
consul:port因为都映射出来了,所以可以是8501-8506、8521任一个端口(指定哪个就注册在哪个节点下面)
instance-id本服务的id,同名服务这个id要不同才好区分
serviceName服务名称,服务消费者靠这个找到服务
hostname告诉consul本服务的IP
server:port指定并告诉consul本服务的端口
7.完善client代码
ConsulClientApplication.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ConsulClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConsulClientApplication.class, args);
}
}
CallHelloController.java
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class CallHelloController {
@Autowired
private LoadBalancerClient loadBalancer;
@RequestMapping("/call")
public String call() {
ServiceInstance serviceInstance = loadBalancer.choose("consul-server");
System.out.println("服务地址:" + serviceInstance.getUri());
System.out.println("服务名称:" + serviceInstance.getServiceId());
String callServiceResult = new RestTemplate().getForObject(serviceInstance.getUri().toString() + "/hello", String.class);
System.out.println(callServiceResult);
return callServiceResult;
}
}
ServiceController.java
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ServiceController {
@Autowired
private LoadBalancerClient loadBalancer;
@Autowired
private DiscoveryClient discoveryClient;
/**
* 获取所有服务
*/
@RequestMapping("/services")
public Object services() {
return discoveryClient.getInstances("consul-server");
}
/**
* 从所有服务中选择一个服务(轮询)
*/
@RequestMapping("/discover")
public Object discover() {
return loadBalancer.choose("consul-server").getUri().toString();
}
}
application.yml
spring:
cloud:
consul:
host: 127.0.0.1
port: 8503
discovery:
register: false
application:
name: spring-cloud-consul-client
server:
port: 8601
register: false表示不注册到consul