Consul微服务搭建

Posted by BY annie dong on September 27, 2018

到现在也没有实践过微服务的我…..
这个例子的github地址,https://github.com/dongjx/vagrant-consul-cluster


微服务架构

将一个完整的应用(单体应用)按照一定的拆分规则拆分成多个不同的服务,每个服务都能独立地进行开发、部署、扩展。服务于服务之间通过注入RESTful api或其他方式调用

项目规划

项目名称 端口 描述 URL
ConsulCluster 8500 注册中心  
UserService 8600 服务提供者 /users
AgentService 8601 服务提供者 /agents
ConsumerService 8602 服务消费者 /

consul的安装与启动

  1. 安装brew install consul
  2. 启动 ./consul agent -dev # -dev表示开发模式运行,另外还有-server表示服务模式运行
  3. 访问http://127.0.0.1:8500/ui/

consul常用命令

命令 解释 示例
agent 运行一个consul agent consul agent -dev
join 将agent加入到consul集群 consul join IP
members 列出consul cluster集群中的members consul members
leave 将节点移除所在集群 consul leave

consul常用命令

consul的高可用

使用vagrant来创建consul集群

主机名称 IP 作用 是否允许远程访问
consul1 172.20.20.10 consul server
consul2 172.20.20.11 consul client
consul3 172.20.20.12 consul client

安装与配置vagrant

  1. 安装brew cask install virtualbox
    如果有安装不成功,可能是需要到System Preferences → Security & Privacy → General点一下右下角的allow
  2. mkdir consulcluster
  3. cd consulcluster
  4. vagrant init centos/7
  5. vim Vagrantfile 并修改:
# -*- mode: ruby -*-
# vi: set ft=ruby :

$script = <<SCRIPT

echo "Installing dependencies ..."
yum install -y epel-release
yum install -y jq
yum install -y unzip

echo "Determining Consul version to install ..."
CHECKPOINT_URL="https://checkpoint-api.hashicorp.com/v1/check"
if [ -z "$CONSUL_DEMO_VERSION" ]; then
    CONSUL_DEMO_VERSION=$(curl -s "${CHECKPOINT_URL}"/consul | jq .current_version | tr -d '"')
fi

echo "Fetching Consul version ${CONSUL_DEMO_VERSION} ..."
cd /tmp/
curl -s https://releases.hashicorp.com/consul/${CONSUL_DEMO_VERSION}/consul_${CONSUL_DEMO_VERSION}_linux_amd64.zip -o consul.zip

echo "Installing Consul version ${CONSUL_DEMO_VERSION} ..."
unzip consul.zip
sudo chmod +x consul
sudo mv consul /usr/bin/consul

SCRIPT

# Specify a custom Vagrant box for the demo
DEMO_BOX_NAME = "centos/7"

# Vagrantfile API/syntax version.
# NB: Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = DEMO_BOX_NAME

  config.vm.provision "shell", inline: $script

  config.vm.define "consul1" do |consul1|
      consul1.vm.hostname = "consul1"
      consul1.vm.network "private_network", ip: "172.20.20.10"
  end

  config.vm.define "consul2" do |consul2|
      consul2.vm.hostname = "consul2"
      consul2.vm.network "private_network", ip: "172.20.20.11"
  end

  config.vm.define "consul3" do |consul3|
      consul3.vm.hostname = "consul3"
      consul3.vm.network "private_network", ip: "172.20.20.12"
  end
end

  1. vagrant up, 三个虚拟机启动

启动虚拟机上的consul服务

  1. 启动consul1的服务:
vagrant ssh consul1
su -    //默认password: vagrant
nohup consul agent -data-dir /tmp/consul1 -node=consul1 -bind=172.20.20.10 -datacenter=dc1 -ui -client=172.20.20.10 -server -bootstrap-expect 1 &
  1. 启动consul2的服务:
vagrant ssh consul2
su -    //默认password: vagrant
nohup consul agent -data-dir /tmp/consul2 -node=consul2 -bind=172.20.20.11 -datacenter=dc1 -ui &
  1. 启动consul3的服务:
vagrant ssh consul3
su -    //默认password: vagrant
nohup consul agent -data-dir /tmp/consul3 -node=consul3 -bind=172.20.20.12 -datacenter=dc1 -ui -client=0.0.0.0 &
  1. 将consul2, consul3加到consul1
vagrant ssh consul2
su -    //默认password: vagrant 
consul join 172.20.20.10

vagrant ssh consul3
su -    //默认password: vagrant
consul join 172.20.20.10
  1. 查看集群状态:
> consul members
Node     Address            Status  Type    Build  Protocol  DC   Segment
consul1  172.20.20.10:8301  alive   server  1.2.3  2         dc1  <all>
consul2  172.20.20.11:8301  alive   client  1.2.3  2         dc1  <default>
consul3  172.20.20.12:8301  alive   client  1.2.3  2         dc1  <default>
  1. 访问172.20.20.10:8500

服务提供方

UserService(spring-boot + mvn)

  1. 在pom.xml中加入依赖
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>

spring-boot-starter-actuator 是health check的依赖

  1. 修改xxxApplication.java
@EnableDiscoveryClient
@SpringBootApplication
public class MicroserviceProducerUserApplication {

	public static void main(String[] args) {
		SpringApplication.run(MicroserviceProducerUserApplication.class, args);
	}
}
  1. 修改application.properties
server.port=8600
spring.application.name=UserService
spring.cloud.consul.host=172.20.20.10
spring.cloud.consul.port=8500
spring.cloud.consul.discovery.register=true
  1. 加入users api, /users
    详情请看代码,https://github.com/dongjx/vagrant-consul-cluster/tree/master/microservice-producer-user

  2. 访问consul的控制台 http://127.20.20.10:8500 ,可以看到注册上的服务信息, 或访问 http://172.20.20.10:8500/v1/agent/services
    avatar

Agent Service

类似UserService, 提供api /agents

服务消费者

  1. 类似UserService, 创建ConsumerService(消费者可以注册到Consul也可以不注册spring.cloud.consul.discovery.register=false)
  2. 在ConsumerService中,调用其他服务
@RestController
public class HomeController {
    @Autowired
    private LoadBalancerClient loadBalancerClient;
    @Autowired
    private DiscoveryClient discoveryClient;
    @Autowired
    private RestTemplate restTemplate;

    /**
     * 获取所有服务
     */
    @GetMapping("/services")
    public Object services() {
        return discoveryClient.getInstances("UserService");
    }

    @GetMapping
    public List index() {
        ServiceInstance serviceInstance = loadBalancerClient.choose("UserService");
        System.out.println("服务地址:" + serviceInstance.getUri());
        System.out.println("服务名称:" + serviceInstance.getServiceId());

        List callServiceResult = restTemplate.getForObject(serviceInstance.getUri().toString() + "/users", List.class);
        System.out.println(callServiceResult);
        return callServiceResult;
    }
}

  1. 启动两个UserService的实例
java -Dserver.port=8503 -jar target/microservice-producer-user-0.0.1-SNAPSHOT.jar
java -Dserver.port=8600 -jar target/microservice-producer-user-0.0.1-SNAPSHOT.jar
  1. 启动AgentService

  2. 启动ConsumerService
    访问http://localhost:8602/services查看所有services

访问http://localhost:8602/

ServerList:ConsulServerList{serviceId='UserService', tag=null}
服务地址:http://10.206.20.242:8503
服务名称:UserService
[annie, zoe]
2018-10-09 17:44:05.976  INFO 47637 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty  : Flipping property: UserService.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
服务地址:http://10.206.20.242:8600
服务名称:UserService
[annie, zoe]

发现强大的Consul已经实现了负载均衡

参考资料

使用Spring Cloud与Docker实战微服务