更新中,关注不断更…
这里讲的是基于springboot和springboot alibaba的微服务,Spring Boot和Spring Boot Alibaba都是基于Spring框架的开源框架,用于简化应用程序的开发和部署。
这篇文章里会介绍微服务的整体概念,目前国内常用的组件,以及国内使用非常广泛的Snowy框架。
首先说一下微服务的概念,相信很多小伙伴已经对单体架构和SOA架构有所了解,当然如果没有了解过也不用着急,这里大致讲一下:
单体架构:将系统所有功能,包括前端界面、后端服务全部在同一个工程上开发,最终将所有模块、所有功能打包在一起放在一个进程上运行。
SOA架构:粗颗粒度的、松耦合的、面向服务的架构,在架构中使用一个标准 的通信协议,通过网络提供应用程序的业务功能服务,且所有服务都是完全独立部署和维护的,并且可以组合使用。
SpringCloud是目前国内使用最广泛的微服务框架。官网地址:https://spring.io/projects/spring-cloud
SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验。
所以刚入手SpringCloud的家人们可以简单理解成一个SpringCloud项目是把一个整体的SpringBoot项目拆成很多小的SpringBoot项目并且集成上优秀组件。
本文中会介绍feign,ribbon,nacos,gateway,rabbitMQ,redis,Sentinel,Seata,以及docker部署工具。
下面这个是一个典型的微服务架构,整个项目拆分成四个模块。
这里说一下微服务架构的几个原则:
- 不同微服务,不要重复开发相同业务
- 微服务数据相互独立,不要访问其他服务的数据库
- 微服务可以将自己的业务暴露为接口,供其他的微服务调用
看到上面的图,有些小伙伴就会想到一个问题,不同的微服务会部署到不同的服务器上,这样就会涉及到一个远程调用的问题,那么这里就开始介绍SpringCloud的第一个组件——feign。
Feign是一个声明式的http客户端,官方地址:https://github.com/OpenFeign/feign
其作用就是帮助我们优雅的实现http请求的发送,解决远程调用的问题。
远程调用简称RPC(Remote Procedure Call),简单来说就是调用方和被调用方不在同一个机器上,可以对比着“本地过程调用”理解这一概念。
这里我们先看一下官方文档:
这段话总结一下就是Feign是以添加注释的形式使用的。
Feign的具体使用方法如下:
- 引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
- 添加注解
在启动类上加上 @EnableFeignClients 注解
@EnableFeignClients
@SpringBootApplication
public class OrderApplication{
public static void main(String[] args){
SpringApplication.run(OrderApplication.class,args);
}
}
- 编写Feign客户端
import org.springframework.cloud.openfeign.Feignclient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.Pathvariable;
//指定绑定服务为userservice
@FeignClient("userservice")
public interface UserClient{
@GetMappring("/user/{id}")
User findById(@PathVariable("id") Long id);
}
这个客户端主要是基于SpringMVC的注解来声明远程调用的信息
- 测试
@Autowired
private UserClient userClient;
public Order queryOrderById(Long orderId){
//1.查询订单(假设这里已经定义好了order实体类)
Order order = orderMapper.findById(orderId);
//2.利用Feign发起http请求,查询用户
User user = userClient.findById(order.getUserId());
//3.封装user到order
order.SetUser(user);
//4.返回
return order;
}
要是有用过RestTemplate的小伙伴就会发现Feign要整洁很多,可读性也更高。
Feign还可以支持很多的自定义配置,如下表所示:
类型 | 作用 | 说明 |
---|---|---|
feign.Logger.Level | 修改日志级别 | 包含四种不同的级别:NONE、BASIC、HEADERS、FULL |
feign.codec.Decoder | 响应结果的解析器 | http远程调用的结果做解析,例如解析json字符串为java对象 |
feign.codec.Encoder | 请求参数编码 | 将请求参数编码,便于通过http请求发送 |
feign.Contract | 支持的注解格式 | 默认是SpringMVC的注解 |
feign.Retryer | 失败重试机制 | 请求失败的重试机制,默认是没有,不过会使用Ribbon的重试 |
一般情况下,默认值就能满足我们使用,如果要自定义时,只需要创建自定义的@Bean覆盖默认Bean即可。
基于配置文件修改feign的日志级别可以针对单个服务:
feign:
client:
config:
userservice: # 针对某个微服务的配置
loggerLevel: FULL # 日志级别
也可以针对所有服务:
feign:
client:
config:
default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
loggerLevel: FULL # 日志级别
NONE:不输出日志信息。
BASIC:仅输出请求方法、URL、响应状态码和执行时间四个基本信息。
HEADERS:输出BASIC级别的信息,并且输出请求和响应的头信息。
FULL:输出完整的请求和响应的详细信息,包括请求和响应的正文。
基于Java代码来修改日志级别:先声明一个类,然后声明一个Logger.Level的对象:
public class DefaultFeignConfiguration {
@Bean
public Logger.Level feignLogLevel(){
return Logger.Level.BASIC; // 日志级别为BASIC
}
}
如果要全局生效,将其放到启动类的@EnableFeignClients这个注解中:
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class)
如果是局部生效,则把它放到对应的@FeignClient这个注解中:
@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration.class)
我们在使用中还会遇到Feign性能优化的问题,这里主要使用的就是用连接池替换Feign默认的URLConnection。