Spring Cloud
SpringCloud旨在快速搭建分布式微服务架构,实现大型项目的功能拆分,将不同服务功能拆分为单独的模块。
SpringCloud的基础功能:
服务治理: Spring Cloud Eureka
客户端负载均衡: Spring Cloud Ribbon
服务容错保护: Spring Cloud Hystrix
声明式服务调用: Spring Cloud FeignAPI
网关服务:Spring Cloud Zuul
分布式配置中心: Spring Cloud Config
当搭建了多个SpringCloud微服务后,首先要解决的问题便是服务间的通讯和调用问题,因此引入Eureka在SpringCloud中起到服务注册中心的作用。系统中每个SpringCloud微服务都需要在Eureka完成注册,记录服务相关信息,最重要的是记录服务名与服务提供服务器IP地址的映射。当某个模块想要调用某微服务时,并不是直接访问服务提供方主机(主机IP可能变动,维护困难,且主机状态无法监控),而是在访问Eureka服务注册中心根据服务名查询服务提供方的IP地址,进而访问。
在Eureka方面,不仅要维护各服务的注册信息并相应服务查询请求,还需要持续监测服务提供方的“心跳”,以保证服务的可达性,同时Eureka也负责服务调用的负载均衡。
Feign
Feign意为伪装,伪装的即是微服务提供方。在Spring Cloud微服务架构中,时常会遇到微服务间相互调用的场景,Feign实现了声明式服务调用,使得微服务间可以用Java接口注解的方式调用Http请求,而不用像Java中通过封装HTTP请求报文的方式直接调用。在pom里引入相关依赖,再在SpringCloud启动类上添加@EnableFeignClients注解,即可开启Feign功能。
@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
public class Service2Application {
public static void main(String[] args) {
SpringApplication.run(Service2Application.class, args);
}
}`
开启之后即可定义代表服务的接口,并添加@FeignClient注解,value表示服务名,不同方法使用不同的路径映射。
@FeignClient(value ="service1")
public interface TestService1Feign {
@PostMapping("/call")
String receiveCallAndResponse(@RequestBody TestParam testParam);
}`
在服务提供方,需要提供该接口具体的实现,在服务消费方,仅需持有该服务的接口及相应依赖。准备工作完成后,消费方即可如调用本地方法一样调用远程微服务。
Feign通过RequestInterceptor将用户信息填充进请求头
Feign 支持请求拦截器,在发送请求前,可以对发送的模板进行操作,例如设置请求头等属性,自定请求拦截器需要实现 feign.RequestInterceptor 接口,该接口的方法 apply 有参数 template ,该参数类型为 RequestTemplate,我们可以根据实际情况对请求信息进行调整,示例如下:
import feign.RequestInterceptor;
import feign.RequestTemplate;
public class MyRequestInterceptor implements RequestInterceptor{
public void apply(RequestTemplatetemplate){
template.header("Authorization","123");
}
}
定义了拦截器后,在FeignClient处添加相应配置:
@FeignClient( name = "order-vr-service", configuration = OrderVrFeignService.Configuration.class)
public interface OrderVrFeignService {
class Configuration {
@Bean
RequestInterceptor signInterceptor() {
return new MyRequestInterceptor();
}
}
}
服务端可以通过HttpServletRequest获取到前面传递的参数,具体获取逻辑如下:
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
if (requestAttributes != null) {
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
request.getHeader("Authorization");
}
就实现了各个微服务之间参数的传递。