服务注册与发现

本文主要内容:

  • 服务注册与发现的作用
  • 准备工作
  • 服务注册
  • 服务发现
  • 客户端发现服务
  • 服务注册与发现工作原理
  • 附源码

服务注册与发现作用

  • 服务注册:服务进程在注册中心注册自己的位置。它通常注册自己的主机和端口号,有时还有身份验证信息,协议,版本号,以及运行环境的详细资料。

  • 服务发现:客户端应用进程向注册中心发起查询,来获取服务的位置。服务发现的一个重要作用就是提供一个可用的服务列表

准备工作

  • 下载 Consul 镜像
    docker pull consul:0.9.2
  • 安装 consul-template
    brew install consul-template
  • 安装 nginx
    brew install nginx
  • 启动 nginx
    brew services restart nginx
  • 启动 Consul
    docker run -d -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8600:8600 consul:0.9.2 agent -dev -bind=0.0.0.0 -client=0.0.0.0
  • 点击此处查看 Consul 服务

服务注册

  • 在 build.gradle 中加入依赖
ext {
     springCloudVersion = 'Dalston.SR4'
}
 dependencyManagement {
     imports {
         mavenBom "org.springframework.cloud:spring-cloud-starter-parent:${springCl
 oudVersion}"
    }
}
 dependencies {
     ...
     compile('org.springframework.boot:spring-boot-starter-actuator')
     compile('org.springframework.cloud:spring-cloud-starter-consul-discovery')
     ...
}
  • bootstrap.yml 中加入配置
  spring:
   cloud:
     consul:
       enabled: true
       hostname: localhost
       port: 8500
       ribbon:
         enabled: true
       discovery:
         enabled: true
         register: true
  • 在项目的入口加入注解
@SpringBootApplication
@EnableDiscoveryClient  //加入此注解
 public class MstUserServiceApplication {
     public static void main(String[] args) {
         SpringApplication.run(MstUserServiceApplication.class, args);
  } 
}

到此,我们的服务已经注册成功,点击此处查看服务注册,结果如下图:

红色选中区域就是我们注册的服务 mst-user-service,此时我们注册的服务是失败的,由于健康检查没过

  • 健康检查
    WebSecurityConfig.java 中加入:
http.authorizeRequests()
            .antMatchers(HttpMethod.GET, "/health").permitAll()
            .anyRequest().authenticated();

重启 mst-user-service 服务,再次点击此处查看服务注册,结果如下图:

至此,我们 mst-user-service 服务已经注册成功。接下来,服务发现。

服务发现

按照上述服务注册的方式,将该服务先用 consul 注册

  • 在发现方 build.gradle 中加入依赖
dependencies {
     ...
     compile('org.springframework.cloud:spring-cloud-starter-feign')
     ... 
}
  • 在发现方入口加入注解
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients  // 加入此注解
 public class MstOrderServiceApplication {
     public static void main(String[] args) {
         SpringApplication.run(MstOrderServiceApplication.class, args);
    } 
}
  • 创建 UserClient 接口,并在发现方写一个跨服务调用的接口
@FeignClient("mst-user-service")  // 此处名字应与我们在 Consul 中注册的名字一致
 public interface UserClient {
     @GetMapping("/api/users/names")
     List getUserNames();
}
  • 重启发现方服务,发送请求。

客户端发现服务——Consul Template + Nginx

  • 设置 Consul Template
    mkdir consule-template && cd consule-template

  • 生成 Consul Template Config 文件

cat >> ./config.json << EOF
 {
   "consul": {
     "address": "http://127.0.0.1:8500"
   },
   "template": {
     "source": "./config.ctmpl",
     "destination": "/usr/local/etc/nginx/servers/ms-nginx.conf",
     "command": "brew services reload nginx"
  }
}
EOF
  • 生成 Nginx 模板
{{range services}} {{$name := .Name}} {{$service := service .Name}}
 upstream {{$name}} {
   #zone upstream-{{$name}} 64k;
   {{range $service}}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1;
   {{else}}server 127.0.0.1:65535; # force a 502{{end}}
 } {{end}}
 server {
   listen 8999 default_server;
 {{range services}} {{$name := .Name}}
   location ~* {{ $name }} {
     proxy_pass http://{{$name}};
   }
{{end}}
   location / {
     root /usr/share/nginx/html/;
     index index.html;
} }
EOF
  • 启动 Consul Template
    consul-template -config ./config.json

  • 查看生成好的 nginx 模板
    vim /usr/local/etc/nginx/servers/ms-nginx.conf

  • Consul 中添加 Key/Value
    matchers/mst-users-service -> /api/(users)
    matchers/mst-order-service -> /api/(goods)
    点此查看 Consule Key/Value

  • 修改 config.ctmpl
    使用下面的代码,替换 config.ctmpl 中同位置的代码

  ...
 {{range services}} {{$name := .Name}}
   {{if (printf "matchers/%s" $name | keyExists)}}
   location ~* {{ printf "matchers/%s" $name | key }} {
     proxy_pass http://{{$name}};
   }
   {{end}}
 {{end}}
...
  • 重启 Consul Template

  • 查看生成好的 nginx 模板

此时,我们可以发请求到 Nginx 对应的 Port 来完成我们的跨服务调用。

服务注册与发现工作原理

  • 当 Service A 启动的时候,会向 Consul 发送一个 POST 请求,告诉 Consul 自己的 IP 和 Port。
  • Consul 接收到 Service A 的注册后,每隔 10s(默认)会向 Service A 发送一个健康检查的请求,检验 Service A 是否健康
  • 当 Service B 发送 GET 方式请求 /api/getA 到 Service A 时,会先从 Consul 中拿到一个存储服务 IP 和 Port 的临时表,从表中拿到 Service A 的 IP 和 Port 后再发送 GET 方式请求 /api/getA
  • 该临时表每隔 10s 会更新,只含有通过健康检查的 Service

附源码

mst-user-service
mst-order-service
consule-template

你可能感兴趣的:(服务注册与发现)