背景
目前公司还存在诸多前后端未分离项目(后面简称FM
项目),开发同学在本地只能联调alpha
环境,但是在项目转测转演之后,测试同学提的jira
单都是hwbeta
、gamma
环境的,因此开发同学为了复现问题场景需要在alpha
环境造单,或者麻烦测试同学造单,此过程非常低效。
分析
我们以本地启动webagent
网关服务联调本地agentBuy-service
服务为例分析流程。
agentBuy-service
服务是一个controller
层服务,调用其他远程服务获取数据并注入到页面文件(ftl
)中,然后freemarker
引擎将ftl
编译成html
并返回给浏览器
远程服务调用过程
现在我们深度分析下远程服务调用过程,先来看看Euraka
是如何注册和发现服务的,Eureka
官方结构图:
Spring-Cloud Euraka
是Spring Cloud
集合中一个组件,它是对Euraka
的集成,用于服务注册和发现。Eureka
是Netflix
中的一个开源框架。它和 zookeeper
、Consul
一样,都是用于服务注册管理的,同样,Spring-Cloud
还集成了Zookeeper
和Consul
。
Eureka
由多个instance
(服务实例)组成,这些服务实例可以分为两种:Eureka Server
和Eureka Client
。为了便于理解,我们将Eureka client
再分为Service Provider
和Service Consumer
。
Eureka Server
为服务注册中心,向外暴露自己的地址,负责管理、记录服务提供者的信息,同时将符合要求的服务提供者地址列表返回服务消费者Service Provider
为服务提供者,在服务启动后,服务提供者向Eureka
注册自己的IP
、端口、提供服务等信息,并定时续约更新自己的状态等Service Consumer
为服务消费者,通过Eureka Server
发现得到所需服务的提供者地址信息,然后向服务提供者发起远程调用
agentBuy-service
是一个Maven Web
项目
- 集成
Spring MVC
搭建前后端未分离(MVC
)项目; - 集成
Eureka
搭建消费者服务(Service Consumer
),用于服务发现或者说定位服务; - 集成
Ribbon
实现客户端负载均衡,Spring Cloud Ribbon
是一个基于HTTP
和TCP
的客户端负载均衡工具,可以让我们轻松地将面向服务的REST
模版请求自动转换成客户端负载均衡的服务调用; - 集成
Feign
帮助我们定义和实现依赖服务接口的定义。在Spring Cloud feign
的实现下,只需要创建一个接口并用注解方式配置它,即可完成服务提供方的接口绑定,简化了在使用Spring Cloud Ribbon
时自行封装服务调用客户端的开发量。也就是说Feign
封装好了与其他服务的请求、响应处理等;
以订单服务远程调用库存服务为例,描述Eureka
、Ribbon
、Feign
三者之间的关系:
参考:一文读懂SpringCloud与Eureka,Feign,Ribbon,Hystrix,Zuul核心组件间的关系
构建agentBuy-service
消费者服务
在pom
文件中添加Eureka-client
依赖
com.netflix.eureka
eureka-client
javax.servlet
servlet-api
在eureka-client.properties
配置文件中增加相关配置信息,因为agentBuy-service
消费者服务不需要提供服务给其他服务,所以不需要注册到注册中心(Eureka Server
),设置不需要注册eureka.registration.enabled=false
和eureka.registerWithEureka=false
// eureka-client.properties
###Eureka Client configuration for Sample Eureka Client
# see the README in eureka-examples to see an overview of the example set up
# note that for a purely client usage (e.g. only used to get information about other services,
# there is no need for registration. This property applies to the singleton DiscoveryClient so
# if you run a server that is both a service provider and also a service consumer,
# then don't set this property to false.
eureka.registration.enabled=false # 表示是否注册到Eureka Server,默认为true
## configuration related to reaching the eureka servers
eureka.preferSameZone=true
eureka.shouldUseDns=false
eureka.registerWithEureka=false # 表示是否将自己注册到Eureka Server,默认为true
eureka.serviceUrl.default=http://10.118.71.204:8761/eureka/ # 注册中心地址
eureka.appinfo.replicate.interval=10
eureka.vipAddress=agentbuy-service # 定义服务名变量
eureka.name=${eureka.vipAddress} # 服务名,SpringCloud中服务调用的依据
eureka.port=8001 # 服务端口
#eureka.ipAddr=192.168.29.170
#eureka.instanceId=${eureka.vipAddress}:${eureka.port}
#eureka.hostname=${eureka.ipAddr}
eureka.homePageUrlPath=/${eureka.vipAddress}
#eureka.statusPageUrlPath=/${eureka.vipAddress}/status
#eureka.healthCheckUrlPath=/${eureka.vipAddress}/health
eureka.lease.renewalInterval=5
eureka.lease.duration=15
eureka.decoderName=JacksonJson
agentBuy-service
远程调用inquiry-service
在发布询价页面会调用agentBuy-service
服务中/getdeliveryaddresses/{companyId}/user/{userLoginId}
接口获取收获地址,该接口远程调用了inquiry-service
服务的方法获取收获地址
使用构造器创建
Bean
实例,constructor-arg
子元素配置一个构造器参数,给FeignClientBuilder
中的configAgentUrl
属性(远程服务地址)赋值api.intra.url
,其中api.intra.url
变量在application.properties
配置文件中定义api.intra.url=http://alpha-api.intra.casstime.com
上述远程调用借助Feign
完成,但是与平时远程调用的方式有所不同,上面采用FeignClientBuilder
动态创建FeignClient
实例去发起远程调用,而不是使用@Autowired
注解让 spring
完成 bean
自动装配的工作生成实例发起远程调用
@Autowired
注解方式:
@FeignClient(name = "inquiry-service")
public interface InquiryClient extends InquiryService{
}
然后向Spring
容器中,注入FeignClient
实例:
@Autowired private InquiryClient inquiryClient;
这是因为SPI
包中提供的feign
接口,是依赖于Spring Boot
的,因此要求外部系统必须是Spring Boot
应用,同时由于feign
接口配置中没有指定服务调用的url
地址,而采用指定服务名的方式,导致外部系统如果想调用feign
接口,必须要和用户权限服务注册在同一个注册中心上。我们的agentBuy-service
不是Spring Boot
服务,采用FeignClientBuilder
动态创建FeignClient
实例可以摆脱对Spring Boot
的依赖。
agentBuy-service
服务本地联调其他环境
上面说到agentBuy-service
是一个freemarker web
服务,如果需要在本地联调hwbeta、gamma
环境,只需要将远程调用服务地址指向hwbeta、gamma
环境
(1)通过网关webagent
走本地agentBuy-service
(2)更改agentBuy-service
远程服务调用地址
因为agentBuy-service
采用FeignClientBuilder
动态创建FeignClient
实例去发起远程调用,通过指定FeignClientBuilder
中configAgentUrl
可以跨Eureka
调用服务,不需要通过Eureka Server
注册中心定位服务