• Stars
    star
    123
  • Rank 290,145 (Top 6 %)
  • Language
    Go
  • License
    MIT License
  • Created about 8 years ago
  • Updated almost 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A microservices architecture app powered by golang.

Microservice-app

一. 简介

该项目是基于go语言搭建的微服务架构应用. 包含如下组件:

  1. 服务注册中心 etcd
  2. Api 网关
  3. Feed 服务
  4. Profile 服务
  5. Topic 服务
  6. 监控组件: prometheus + grafana
  7. 跟踪组件: zipkin + elasticsearch

其中Feed, Profile, Topic 启动时会向etcd注册服务, Apigateway 通过调用这三个服务的客户端 Watch 到相应服务的注册Key, 同时得到服务的地址. 当服务实例个数动态伸缩时, Apigateway 也会实时响应变化.

结构如下:

block

二. 项目源码

目录 介绍
apigateway 注册app所有endpoint.
client 所有访问微服务的客户端, 供apigateway调用. 提供服务发现,负载均衡,错误重试和故障降级等功能.
cmd 各个服务的启动命令.
docker 构建各个服务的docker镜像.
feed feed服务.
monitor 监控组件.
profile profile服务.
proto 服务间IPC方式采用grpc.
topic topic服务.
tracer 分布式跟踪.
vagrant 虚拟化分布式环境, 采用传统方式部署应用.

三. 部署应用

目前使用了两种应用部署方式:传统部署方式和容器化部署方式

1. 传统部署

如果你熟悉vagrant, vagrant目录下有具体部署细节. 参考Vagrantfileprovision.sh 总的来讲,项目使用vagrant虚拟化了5个节点, 节点0部署etcd, 节点1-4分别部署service-feed, service-profile, service-topic, apigateway.

 $nodes = 5
 Vagrant.configure("2") do |config|
     config.vm.box = "centos/7"
     (0..($nodes - 1)).each do |i|
         config.vm.define name="node-#{i}", primary: (i == 0), autostart: (i == 0) do |node|
             node.vm.hostname = name
             node.vm.network "private_network", ip: "192.168.50.#{10+i}"
             node.vm.provision "shell", path: "provision.sh", env: {"LOCAL_IP" => "192.168.50.#{10+i}", "ETCD_ENDPOINT" => "http://192.168.50.10:2379"}
         end
     end
 end

部署前请确保vagrant-1.9.0, 至于为什么是该版本, 个人认为该版本目前(2016-12-10)来看最稳定,bug最少.

在vagrant目录下, 使用如下命令, 启动所有节点. 该命令第一次启动时会创建5台虚拟机node-0 ~ node-4. 并下载安装所需的可执行文件.

# 注意: 首次启动会比较慢, 具体时间取决于网络.
$ vagrant up /node-./

启动后, 可以通过vagrant ssh + node-* 连接任何虚拟机. 例如,如果想查看apigateway是否运行, 可以执行如下命令:

$ vagrant ssh node-4
$ ps -ef | grep apigateway
$ exit

如果启动成功, 那么可以访问我们的服务了

$ curl -XPUT "http://192.168.50.14:8080/api/feed/create_feed" -d '{"id": 100, "user_id": 123, "content": "hello world"}'  // 发布feed1
$ curl -XPUT "http://192.168.50.14:8080/api/feed/create_feed" -d '{"id": 101, "user_id": 123, "content": "goodbye!"}'     // 发布feed2
$ curl -XGET "http://192.168.50.14:8080/api/feed/get_feeds?user_id=123&&size=2"                                           // 拉取feed列表

将会显示

{
    "feeds": [
        {
            "id": 100,
            "user_id": 123,
            "content": "hello world"
        },
        {
            "id": 101,
            "user_id": 123,
            "content": "goodbye!"
        }
    ]
}

注意: 默认每一个微服务只启动一个实例, 如果想看多个微服务实例, 那么可以到某个节点上手动启动. 例如:

$ vagrant ssh node-2
$ nohup feed -addr=$LOCAL_IP:8082 -etcd.addr=$ETCD_ENDPOINT 0<&- &>/dev/null &  //nohup 忽略用户退出时的hup信号, 这样当退出ssh时feed进程不会受到影响. 实际上feed进程源码中实现了对某些信号的处理.
$ exit

这样, 对于feed相关的请求,apigateway会把每一个请求通过round robin的方式均衡的打到两个feed实例上,实现进程内负载均衡. 同样需要注意: 原则上说, 微服务都应该是无状态的. 然而为了简单,该项目中的微服务实例都是采用内存存储. 所以在多实例环境下, 如果你发布了一条feed, 却没有拉取到, 那么多试几次即可.

2. 容器化部署

如果你对docker熟悉的话, docker目录下提供了构建镜像的脚本 build.sh.

./build.sh

该脚本生成4个服务的docker镜像, 然后我们通过docker-compose命令启动容器.

docker-compose up -d

启动成功后:

$ curl -XPUT "http://localhost:8080/api/feed/create_feed" -d '{"id": 100, "user_id": 123, "content": "hello world"}'  // 发布feed1
$ curl -XPUT "http://localhost:8080/api/feed/create_feed" -d '{"id": 101, "user_id": 123, "content": "goodbye!"}'     // 发布feed2
$ curl -XGET "http://localhost:8080/api/feed/get_feeds?user_id=123&&size=2"                                           // 拉取feed列表

四. 应用监控

应用监控采用prometheus + grafana + cadvisor + alertmanager.

启动监视器

启动监视器之前请先阅读README.

如果是使用方式1部署的应用, 在monitor目录下, 可以通过如下配置target, 来监视app

- targets: ['localhost:9090','cadvisor:8080', '192.168.50.11:6062', '192.168.50.12:6063', '192.168.50.13:6064', '192.168.50.14:6060']

然后在monitor目录下

$ docker-compose up

这样监视器启动成功.

如果采用方式2部署的应用, docker-compose文件已经配置好. 直接在monitor目录下:

$ docker-compose -f docker-compose.yml.2 up -d

两种方式启动成功后, 都可以通过访问: http://localhost:9090/graph 来查看metrics.

可视化

可视化采用grafana, 它与prometheus结合的很好, 采用该方案可以很好的监控docker容器的状态

打开浏览器 http://localhost:3000, 进入grafana, 添加数据源, Type选择Prometheus, Access选择direct模式, 填写prometheus的url: http://localhost:9090, 勾上默认. Save & test. 退出.

添加dashboard, 导入monitor/grafana/docker_dashboard.json 即可看到下图:

docker_dashboard

五. 跟踪

分布式跟踪系统采用 zipkin + elasticsearch后端, zipkin负责UI和span收集, es负责海量数据存储和索引. 在App中已经集成了zipkin的客户端代码, 只需要在程序执行时设置-zipkin.addr参数即可, 例如:

go run cmd/feed/main.go -etcd.addr=http://localhost:2379 -zipkin.addr=http://localhost:9411/api/v1/spans

tracer目录下提供了一个docker-compose.yml文件, 它在docker/docker-compose.yml的基础上集成了zipkin和elasticsearch. 在该目录下:

$ docker-compose up -d

启动成功后可以通过curl访问:

$ curl -XPUT "http://localhost:8080/api/feed/create_feed" -d '{"id": 100, "user_id": 123, "content": "hello world"}'  // 发布feed1
$ curl -XPUT "http://localhost:8080/api/feed/create_feed" -d '{"id": 101, "user_id": 123, "content": "goodbye!"}'     // 发布feed2
$ curl -XGET "http://localhost:8080/api/feed/get_feeds?user_id=123&&size=2"                                           // 拉取feed列表

这时候跟踪系统已经有了3条数据.

浏览器打开http://localhost:9411, 服务名选择http, 并选择合适的时间范围, 然后点击Find traces, 便可找到这3条traces. 随便点一条进去可以看到如下图所示跟踪轨迹(由于该App功能简单,调用深度目前只有两层):

tracing

六. Todo

  • 使用kubenetes部署整个应用