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实战微服务