一、微服务
1.什么是微服务架构
简单地说, 微服务是系统架构上的一种设计风格, 它的主旨是将一个原本独立的系统 拆分成多个小型服务,这些小型服务都在各自独立的进程中运行,服务之间通过基于HTTP 的RESTful API进行通信协作。 被拆分成的每一个小型服务都围绕着系统中的某一项或一 些耦合度较高的业务功能进行构建, 并且每个服务都维护着自身的数据存储、 业务开发、 自动化测试案例以及独立部署机制。 由千有了轻量级的通信协作基础, 所以这些微服务可 以使用不同的语言来编写。
一个完整的微服务体系至少需要包括:
- CI / CD 也就是自动化部署
- 服务发现
- 统一的PRC协议
- 监控
- 追踪(Tracing)
2.注册中心
因为服务是单独部署的,因此服务间要想相互调用只能通过RPC的方式:部署在机器A上的用户服务通过RPC的方式调用部署在机器B上的订单服务。
这就引入了微服务架构中一个重要的组件:服务发现与注册中心。你要调用订单服务的接口,首先你得知道哪些机器上部署了订单服务,注册中心就是干这个事的,所有的微服务都把自己注册到注册中心,这样注册中心就知道哪个服务在哪些机器上,当有调用请求的时候,由注册中心按一定的负载均衡策略把这个请求落地到具体的机器上,下面是最能说明服务注册中心的一张经典图:
consul
1、consul acl访问控制
type consulServiceRegistry struct {
serviceInstances map[string]map[string]cloud.ServiceInstance
client api.Client
localServiceInstance cloud.ServiceInstance
}
// new a consulServiceRegistry instance
// token is optional
func NewConsulServiceRegistry(host string, port int, token string) (*consulServiceRegistry, error) {
if len(host) < 3 {
return nil, errors.New("check host")
}
if port <= 0 || port > 65535 {
return nil, errors.New("check port, port should between 1 and 65535")
}
config := api.DefaultConfig()
config.Address = host + ":" + strconv.Itoa(port)
config.Token = token
client, err := api.NewClient(config)
if err != nil {
return nil, err
}
return &consulServiceRegistry{
client: *client}, nil
}
func TestConsulServiceDiscovery(t *testing.T) {
host := "127.0.0.1"
port := 8500
token := ""
registryDiscoveryClient, err := extension.NewConsulServiceRegistry(host, port, token)
if err != nil {
panic(err)
}
t.Log(registryDiscoveryClient.GetServices())
t.Log(registryDiscoveryClient.GetInstances("go-user-server"))
}
2、Consul服务注册中心的整体架构
如果要基于Consul作为服务注册中心,那么首先必须在每个服务所在的机器上部署一个Consul Agent,作为一个服务所在机器的代理。然后还得在多台机器上部署Consul Server,这就是核心的服务注册中心。这个Consul Agent可以用来收集你的服务信息然后发送给Consul Server,还会对你的服务不停的发送请求检查他是否健康。然后你要发现别的服务的时候,Consul Agent也会帮你转发请求给Consul Server,查询其他服务所在机器。Consul Server一般要求部署3~5台机器,以保证高可用以及数据一致性。他们之间会自动实现数据同步,而且Consul Server集群会自动选举出一台机器作为leader,其他的Consul Server就是follower。咱们看下面的图,先感受一下这个Consul他整体的架构。
3、Consul如何通过Raft协议实现强一致性?
首先,库存服务注册到Leader Server的时候,会采取Raft协议,要求必须让Leader Server把这条注册数据复制给大部分的Follower Server才算成功。这就保证了,如果你认为自己注册成功了,那么必然是多台Consul Server都有这条注册数据了。如果你刚发送给Leader Server他自己就宕机了,那么这次注册会认为失败。此时,Consul Server集群会重新选举一个Leader Server出来,你需要再次重新注册。这样就可以保证你注册成功的数据绝对不会丢,然后别人发现服务的时候一定可以从Leader Server上获取到最新的强一致的注册数据。
4、Consul如何通过Agent实现分布式健康检查?
最后说说Consul是如何通过各个服务机器上部署Agent来实现分布式健康检查的。集中式的心跳机制,比如传统的Eureka,是让各个服务都必须每隔一定时间发送心跳到Eureka Server。如果一段时间没收到心跳,那么就认为这个服务宕机了。
但是这种集中式的心跳机制会对Eureka Server造成较大的心跳请求压力,实际上平时Eureka Server接收最多的请求之一就是成千上万服务发送过来的心跳请求。
所以Consul在这块进行了架构优化,引入了Agent概念。 每个机器上的Consul Agent会不断的发送请求检查服务是否健康,是否宕机。如果服务宕机了,那么就会通知Consul Server。怎么样?是不是发现各个服务自己不用再发送心跳请求去Server了?减小了Server这部分的压力吧?没错,这就是Consul基于Agent实现的分布式健康检查机制,可以大幅度的减小Server端的压力。这样一来,哪怕你就部署个三五台机器,可以轻松支持成千上万个服务。咱们再来一张图,一起来看看:
3、服务之间如何通信
所有的微服务都是独立部署,运行在自己的进程容器中,所以微服务与微服务之间的通信就是IPC (Inter Process Communication),翻译为进程间通信。进程间通信的方案已经比较成熟了,现在最常见的有两大类:同步调用、异步消息调用。
同步调用
同步调用比较简单,一致性强,但是容易