spring cloud微服务实战:consul+Feign/Ribbon服务注册和远程调用

系统架构的演变 随着互联网的发展,网站应用的规模不断扩大,常规的应用架构已无法应对,分布式服务架构以及微服 务架构势在必行,亟需一个治理系统确保架构有条不紊的演进。

在微服务架构中,通常存在多个服务之间的远程调用的需求。远程调用通常包含两个部分:序列化和通 信协议。常见的序列化协议包括json、xml、hession、protobuf、thrift、text、bytes等,目前主流的 远程调用技术有基于HTTP的RESTful接口以及基于TCP的RPC协议。

(1)RESTful接口 REST,即Representational State Transfer的缩写,如果一个架构符合REST原则,就称它为RESTful架 构。 资源(Resources) 所谓"资源",就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图 片、一首歌曲、一种服务,总之就是一个具体的实在。你可以用一个URI(统一资源定位符)指向它, 每种资源对应一个特定的URI。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地 址或独一无二的识别符。REST的名称"表现层状态转化"中,省略了主语。"表现层"其实指的是"资 源"(Resources)的"表现层"。 表现层(Representation) "资源"是一种信息实体,它可以有多种外在表现形式。我们把"资源"具体呈现出来的形式,叫做它的"表 现层"(Representation)。比如,文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格 式表现,甚至可以采用二进制格式;图片可以用JPG格式表现,也可以用PNG格式表现。URI只代表资源 的实体,不代表它的形式。严格地说,有些网址最后的".html"后缀名是不必要的,因为这个后缀名表示 格式,属于"表现层"范畴,而URI应该只代表"资源"的位置。

状态转化(State Transfer) 访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变 化。互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因 此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。 客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词: GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源 (也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。 综合上面的解释,我们总结一下什么是RESTful架构: 每一个URI代表一种资源; 客户端和服务器之间,传递这种资源的某种表现层; 客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"。 (2)RPC协议 RPC(Remote Procedure Call ) 一种进程间通信方式。允许像调用本地服务一样调用远程服务。RPC 框架的主要目标就是让远程服务调用更简单、透明。RPC框架负责屏蔽底层的传输方式(TCP或者 UDP)、序列化方式(XML/JSON/二进制)和通信细节。开发人员在使用的时候只需要了解谁在什么 位置提供了什么样的远程服务接口即可,并不需要关心底层通信细节和调用过程。

(3)区别与联系

1、HTTP相对更规范,更标准,更通用,无论哪种语言都支持http协议。如果你是对外开放API,例如 开放平台,外部的编程语言多种多样,你无法拒绝对每种语言的支持,现在开源中间件,基本最先支持 的几个协议都包含RESTful。

2、 RPC 框架作为架构微服务化的基础组件,它能大大降低架构微服务化的成本,提高调用方与服务提 供方的研发效率,屏蔽跨进程调用函数(服务)的各类复杂细节。让调用方感觉就像调用本地函数一样 调用远端函数、让服务提供方感觉就像实现一个本地函数一样来实现服务。

在上面一节我们讲了Eureka+Feign/Ribbon,使用Eureka来做注册中心。本章我们讲consul+Feign/Ribbon服务注册和远程调用微服务。

一. 什么是consul

1.1 consul 概述

Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其它分布式服 务注册与发现的方案,Consul 的方案更"一站式",内置了服务注册与发现框 架、分布一致性协议实 现、健康检查、Key/Value 存储、多数据中心方案,不再需要依赖其它工具(比如 ZooKeeper 等)。 使用起来也较 为简单。Consul 使用 Go 语言编写,因此具有天然可移植性(支持Linux、windows和 Mac OS X);安装包仅包含一个可执行文件,方便部署,与 Docker 等轻量级容器可无缝配合。 Consul 的优势: 使用 Raft 算法来保证一致性, 比复杂的 Paxos 算法更直接. 相比较而言, zookeeper 采用的是 Paxos, 而 etcd 使用的则是 Raft。 支持多数据中心,内外网的服务采用不同的端口进行监听。 多数据中心集群可以避免单数据中心 的单点故障,而其部署则需要考虑网络延迟, 分片等情况等。 zookeeper 和 etcd 均不提供多数据中 心功能的支持。 支持健康检查。 etcd 不提供此功能。 支持 http 和 dns 协议接口。 zookeeper 的集成较为复杂, etcd 只支持 http 协议。 官方提供 web 管理界面, etcd 无此功能。 综合比较, Consul 作为服务注册和配置管理的新星, 比较值得关注和研究。

1.2 consul与Eureka的区别

(1)一致性 Consul强一致性(CP) 服务注册相比Eureka会稍慢一些。因为Consul的raft协议要求必须过半数的节点都写入成功才认 为注册成功 Leader挂掉时,重新选举期间整个consul不可用。保证了强一致性但牺牲了可用性。 Eureka保证高可用和最终一致性(AP) 服务注册相对要快,因为不需要等注册信息replicate到其他节点,也不保证注册信息是否 replicate成功 当数据出现不一致时,虽然A, B上的注册信息不完全相同,但每个Eureka节点依然能够正常对外提 供服务,这会出现查询服务信息时如果请求A查不到,但请求B就能查到。如此保证了可用性但牺 牲了一致性。

(2)开发语言和使用 eureka就是个servlet程序,跑在servlet容器中 Consul则是go编写而成,安装启动即可

1.3 consul的下载与安装

Consul 不同于 Eureka 需要单独安装,访问 Consul 官网下载 Consul 的最新版本,我这里是 consul1.5x。根据不同的系统类型选择不同的安装包,从下图也可以看出 Consul 支持所有主流系统。打开官网地址去下载:

https://developer.hashicorp.com/consul/install

我下载linux的,下载后解压。

将consul copy到/usr/local/bin目录下。

然后启动:

已经启动了,打开浏览器 http://192.168.33.10:8500/

可以看到consul控制台界面,目前还没有服务注册。

二 基于consul的服务注册

2.1 创建项目

这里直接copy上一节,订单和产品服务模块

订单pom引入consul , actuator的健康检查

复制代码
<!--springcloud 提供的对基于consul的服务发现-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <!--actuator的健康检查-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

yml文件注册consul

复制代码
  ###开始配置consul的服务注册
  cloud:
    consul:
      host: 192.168.33.10 #consul服务器的主机地址
      port: 8500 #consul服务器的ip地址
      discovery:
        #是否需要注册
        register: true
        #注册的实例ID (唯一标志)
        instance-id: ${spring.application.name}-5
        #服务的名称
        service-name: ${spring.application.name}
        #服务的请求端口
        port: ${server.port}
        #指定开启ip地址注册
        prefer-ip-address: true
        #当前服务的请求ip
        ip-address: ${spring.cloud.client.ip-address}

接着编写接口:

复制代码
@RestController
@RequestMapping("/order")
public class OrderController {

	@Autowired
	private RestTemplate restTemplate;


	@RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
	public Product findById(@PathVariable Long id) {
		Product product = restTemplate.getForObject("http://service-product/product/1",Product.class);;
		return product;
	}

}

启动服务:

看到服务已经注册到consul了。

接下来我们同样配置产品微服务。

产品pom引入consul , actuator的健康检查。

复制代码
 <!--springcloud 提供的对基于consul的服务发现-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <!--actuator的健康检查-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

yml文件我要通过Ribbon来实现负载均衡,所以我要启动2个产品模块。

复制代码
spring:
  profiles: product1
  application:
    name: service-product #服务名称
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.33.10:3306/shop?useUnicode=true&characterEncoding=utf8
    username: homestead
    password: secret
  jpa:
    database: MySQL
    show-sql: false
    open-in-view: true
  ###开始配置consul的服务注册
  cloud:
    consul:
      host: 192.168.33.10 #consul服务器的主机地址
      port: 8500 #consul服务器的ip地址
      discovery:
        #是否需要注册
        register: true
        #注册的实例ID (唯一标志)
        instance-id: ${spring.application.name}-1
        #服务的名称
        service-name: ${spring.application.name}
        #服务的请求端口
        port: ${server.port}
        #指定开启ip地址注册
        prefer-ip-address: true
        #当前服务的请求ip
        ip-address: ${spring.cloud.client.ip-address}
server:
  port: 9008 #端口
---
spring:
  profiles: product2
  application:
    name: service-product #服务名称
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.33.10:3306/shop?useUnicode=true&characterEncoding=utf8
    username: homestead
    password: secret
  jpa:
    database: MySQL
    show-sql: false
    open-in-view: true
  ###开始配置consul的服务注册
  cloud:
    consul:
      host: 192.168.33.10 #consul服务器的主机地址
      port: 8500 #consul服务器的ip地址
      discovery:
        #是否需要注册
        register: true
        #注册的实例ID (唯一标志)
        instance-id: ${spring.application.name}-2
        #服务的名称
        service-name: ${spring.application.name}
        #服务的请求端口
        port: ${server.port}
        #指定开启ip地址注册
        prefer-ip-address: true
        #当前服务的请求ip
        ip-address: ${spring.cloud.client.ip-address}

server:
  port: 9005 #端口

@Configuration 配置Ribbon类:

复制代码
@Configuration   //代表这是一个Spring配置类 spring.xml工厂
public class BasicConfig {
    @Bean
    @LoadBalanced  //实现负载均衡 让对象具有Ribbon负载均衡的特性
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

}

接口实现:

复制代码
@RestController
@RequestMapping("/order")
public class OrderController {

	@Autowired
	private RestTemplate restTemplate;


	@RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
	public Product findById(@PathVariable Long id) {
		Product product = restTemplate.getForObject("http://service-product/product/1",Product.class);;
		return product;
	}

}

这样就完成了2个产品微应用。下面我们来启动2个微应用,启动参数指定:

--spring.profiles.active=product2

启动2个产品微应用:

可以看到有3个微应用注册了。

接着我通过订单来访问产品接口:

通过控制台可以看到刷新一次,请求其中一个,轮询来访问,这样我们就实现了负载均衡。当然他有好几种策略:

我们可以通过继承他的AbstractLoadBalancerRule实现每一种策略。这里就不详细来介绍了,有兴趣的话,自己写一个来实现。

相关推荐
沉迷技术逻辑3 小时前
微服务架构-网关
java·微服务·架构
黄俊懿13 小时前
【深入理解SpringCloud微服务】Seata(AT模式)源码解析——全局事务的提交
java·后端·spring·spring cloud·微服务·架构·架构师
大猫和小黄1 天前
若依微服务全面适配PostgreSQL-OpenGauss数据库
数据库·微服务·postgresql·若依
juma90021 天前
一维光栅拓扑BICs与COMSOL模拟的COMSOL光子晶体超表面单向辐射
consul
没有bug.的程序员1 天前
微服务基础设施清单:必须、应该、可以、无需的四级分类指南
java·jvm·微服务·云原生·容器·架构
天远Date Lab1 天前
Java微服务实战:聚合型“全能小微企业报告”接口的调用与数据清洗
java·大数据·python·微服务
墨痕诉清风1 天前
java漏洞集合工具(Struts2、Fastjson、Weblogic(xml)、Shiro、Log4j、Jboss、SpringCloud)
xml·java·struts·安全·web安全·spring cloud·log4j
没有bug.的程序员1 天前
微服务中的数据一致性困局
java·jvm·微服务·架构·wpf·电商
⑩-1 天前
SpringCloud-Feign客户端实战
后端·spring·spring cloud