---
title: 微服务架构本地尝试(三)-服务发现
---

**本系列在 github 中更新,源码和 docker 都可在 github 项目中找到:[https://github.com/CodFrm/learnMicroService](https://github.com/CodFrm/learnMicroService)**
**GitHub 文章:[点我去 GitHub 看](<https://github.com/CodFrm/learnMicroService/blob/master/doc/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9E%B6%E6%9E%84%E6%9C%AC%E5%9C%B0%E5%B0%9D%E8%AF%95(%E4%B8%89)-%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0.md>)**

> 上一节完成了 api 网关,这一节来了解微服务架构中的服务发现
>
> 我们现在的微服务 rpc 调用我们是直接的填入的 ip 和端口,客户端连接服务端.但是当我们的微服务多起来,而且是集群部署那么问题就出来了,我们不可能每一个都填好 ip 和端口,这样是不方便动态扩容和部署的,而且当我们调用的时候也无法做到很好的负载均衡.关于这个有两种模式,客户端服务发现和服务端服务发现,这里我们只探讨服务端服务发现
>
> 那么我们就需要一个服务中心,微服务进程创建的时候告诉他,我能提供 xx 服务,我的 ip 端口是 xx,然后其他的微服务或客户需要调用的时候来服务中心问,我需要 xx 服务的信息就 OK 了

![](img/03-%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0.assets/service_chart.png)

服务发现的框架常见的有

- zookeeper
- eureka
- etcd
- consul

这里我们选择[Consul](https://www.consul.io/)来实现

## 开始

> 自然和之前一样,继续用我们的 docker

docker-compose.yml 中直接加入如下,然后访问 8500 端口就可以进入面板了

```yml
service_center:
  image: consul
  hostname: service_center
  container_name: micro_service_center
  ports:
    - 8500:8500
    - 8600:8600
    - 8300:8300
  networks:
    - micro
```

![](img/03-%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0.assets/service_consul.png)

## 使用

### 服务注册/发现

[https://www.consul.io/api/agent/service.html#register-service](https://www.consul.io/api/agent/service.html#register-service)

服务注册使用 api,发送请求,这里我用 postman 先来测试添加

官网给了一个例子

```json
PUT /agent/service/register json

{
  "ID": "redis1",# 服务id
  "Name": "redis",# 服务名
  "Tags": [# 标签
    "primary",
    "v1"
  ],
  "Address": "127.0.0.1",# 服务地址
  "Port": 8000,# 服务端口
  "Meta": {# 服务的一些信息
    "redis_version": "4.0"#表示redis版本
  },
  "EnableTagOverride": false,# 是否开启Tag覆盖,更多细节请参考:https://www.consul.io/docs/agent/services.html#enable-tag-override-and-anti-entropy 我也看不太懂啊,hhh
  "Check": {# 校验规则
    "DeregisterCriticalServiceAfter": "90m",
    "Args": ["/usr/local/bin/check_redis.py"],
    "HTTP": "http://localhost:5000/health",
    "Interval": "10s",
    "TTL": "15s"
  },
  "Weights": {# 权重,应该是用于负载均衡的
    "Passing": 10,
    "Warning": 1
  }
}
```

我先尝试自己添加几个服务,然后我的面板上就有了一个新的**post_micro**服务,点进去,虽然都挂了 emmmm 因为我现在还没开启

![](img/03-%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0.assets/service_2.png)

![](img/03-%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0.assets/service_3.png)

```sh
curl -X PUT \
  http://127.0.0.1:8500/v1/agent/service/register \
  -H 'Content-Type: application/json' \
  -H 'Postman-Token: b2089dbe-8ad3-487b-97e0-25217e6ee346' \
  -H 'cache-control: no-cache' \
  -d '{
    "ID": "post2",
    "Name": "post_micro",
    "Tags": [
        "post",
        "v1"
    ],
    "Address": "10.0.75.1",
    "Port": 8004,
    "Check": {
        "DeregisterCriticalServiceAfter": "90m",
        "HTTP": "http://10.0.75.1:8004/post",
        "Interval": "10s"
    }
}'
```

然后 consul 也提供了服务发现(查询)的接口,来试一试,除了这种接口的方式外,还可以使用 DNS,我们只要如果配合 kong 的话需要用这种形式,等下介绍.post_micro 就是我们的服务名了

```sh
curl -X GET \
  http://127.0.0.1:8500/v1/catalog/service/post_micro \
  -H 'Postman-Token: ce54bd1d-c21e-46e0-ae0e-0230de9e6f8d' \
  -H 'cache-control: no-cache'
```

域名默认格式为 servicename.service.consul

```sh
/ # dig @127.0.0.1 -p 8600 post_micro.service.consul SRV

; <<>> DiG 9.11.5 <<>> @127.0.0.1 -p 8600 post_micro.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25596
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 5
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;post_micro.service.consul.     IN      SRV

;; ANSWER SECTION:
post_micro.service.consul. 0    IN      SRV     1 1 8005 0a004b01.addr.dc1.consul.
post_micro.service.consul. 0    IN      SRV     1 1 8004 0a004b01.addr.dc1.consul.

;; ADDITIONAL SECTION:
0a004b01.addr.dc1.consul. 0     IN      A       10.0.75.1
service_center.node.dc1.consul. 0 IN    TXT     "consul-network-segment="
0a004b01.addr.dc1.consul. 0     IN      A       10.0.75.1
service_center.node.dc1.consul. 0 IN    TXT     "consul-network-segment="

;; Query time: 0 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Wed Jan 30 05:02:21 UTC 2019
;; MSG SIZE  rcvd: 266
```

因为 kong 要用 consul 的 dns,整合起来,然后到这里的时候遇到个坑...首先需要 ip 地址,不能是 hostname 了...然后我是在 docker 里面...还需要 docker-compose 静态 ip,可以看我的 compose 文件的变化,然后设置了一个`KONG_DNS_RESOLVER`参数,但还不行,因为你的 dns 变了,`KONG_PG_HOST`之前是 hostname,现在我的 dns 不能解析,所以也要给数据库设置一个静态 ip(设置静态 ip 主要是防止变化后不能使用).之前的容器最好 down 掉,network 也删除,重新来一遍

成功之后在 konga 面板的 info 中可以看到 dns_resolver 是我们设置的值了

![](img/03-%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0.assets/service_4.png)

### 接入网关

然后和前一节一样,添加 service,因为我重新构建了,所以之前的数据是没了的,也没关系,重新来

![添加service](img/03-%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0.assets/service_5.png)

![添加route](img/03-%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0.assets/service_6.png)

有没有发现我前面是添加了两个不同的端口,然后这里没有添加端口了,是的,consul 帮你自动匹配了,负载均衡了解一下,你就当我这俩是集群好了,效果的话,我故意的文件改了一下,刷新出来的页面不同(我只是为了演示效果,实际是绝对不行的...)

![](img/03-%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0.assets/service_7.png)

## End

这一节感觉还不算完全完成,注册和发现的代码我们还没写呢

![](img/03-%E6%9C%8D%E5%8A%A1%E5%8F%91%E7%8E%B0.assets/bqb_1.jpg)

留到下一节好了,今天几乎是配置了一天的环境,下一节预计就要开始容器化微服务了,然后等下吧文章搬到博客去,之前没直接放博客的原因主要是怕半途弃坑,多丢人,2333
