spring cloud 实践
项目结构
config 配置中心
端口:8888,方便起见直接读取配置文件,生产环境可以读取git。application-dev.properties为全局配置。先启动配置中心,所有服务的配置(包括注册中心的地址)均从配置中心读取。
eureka 注册中心
端口:8761,/metadata端点实现metadata信息配置。
zuul 网关
端口:8080,演示解析token获得label并放入header往后传递
core 框架核心包
核心jar包,所有微服务均引用该包,使用AutoConfig实现免配置,模拟生产环境下spring-cloud的使用。
starter spring cloud以及core框架依赖简化starter
provider 服务提供者
api 服务提供者SDK
强制服务消费方只能通过服务提供者提供的SDK包(api项目)进行调用,以便更加方便控制服务消费方的行为:
提供可能的优化,SDK直接读取缓存(SDK只读缓存,写缓存放还是在微服务)。
统计有哪些服务消费者,info端点显示包依赖,通过注册中心遍历所有服务。
方便dubbo平滑迁移,接口加feign注解。
service 服务提供者微服务
端口:18090,服务提供者,无特殊逻辑。
consumer 服务消费者
端口:18090,调用服务提供者。
Restful API 设计规范
/版本/访问控制/域对象
/版本/访问控制/域对象/action/动作
版本
版本为微服务级别,也就是说不存在一个API是v3版,其他API还只是v1版的问题,要升级所有API版本一起升级,但是需要保证之前版本v1-v3还可以使用。
原则上要兼容上一个版本 如果当前是 /v3 则 /v2 要求可以正常使用 /v1 不做要求
如果无法兼容 需要通知所有服务消费者 并约定版本火车 一起上线时间
小技巧
下面swagger注解就可以实现上述要求,路径中的{version}没有限定,其实可以是任意内容,通过swagger文档来进行约定
// v1版api 即将废弃
@ApiOperation("分页查询")
@RequestMapping(value = "/v1/pb/product", method = RequestMethod.GET)
@Deprecated
List selectAll(@RequestParam("offset") Integer offset, @RequestParam("limit") Integer limit);
//ProviderApiAutoConfig.CURRENT_VERSION="v2" 用来替换上面的v1版本
@ApiOperation("带过滤条件和排序的分页查询")
@RequestMapping(value = "/{version}/pb/product", method = RequestMethod.GET)
@ApiImplicitParam(name = "version", paramType = "path", allowableValues = ProviderApiAutoConfig.CURRENT_VERSION, required = true)
Response> selectAllGet(Page page);
// ProviderApiAutoConfig.COMPATIBLE_VERSION="v2,v1" swagger-ui上会显示一个version的下拉框, 默认v2
@ApiOperation(value = "带过滤条件和排序的复杂分页查询")
@ApiImplicitParam(name = "version", paramType = "path", allowableValues = ProviderApiAutoConfig.COMPATIBLE_VERSION, required = true)
@RequestMapping(value = "/{version}/pb/product/action/search", method = RequestMethod.POST)
Response> selectAll(@RequestBody Page page);
访问控制
用于在网关统一进行访问控制, 访问控制分为
pb - public 所有请求均可访问
pt - protected 需要进行token认证通过后方可访问
df - default 网关进行token认证 并且请求参数和返回结果进行加解密
pv - private 无法通过网关访问 只能微服务内部调用
其他 同pv
action
无法用名词+请求方法表述的可以扩展为 /域对象/action/动词 必须为POST方法
例如 POST /users/action/login
问题描述
主要由于使用了API(SDK)为了偷懒,以及Restful API路径中的版本带来的一系列问题。
spring MVC 不支持继承接口中方法参数上的注解(支持继承类、方法上的注解)
API中为了方便,使用feign替代RestTemplate手动调用。带来的问题:springMVC注解想偷懒,只在feign接口写一遍,然后实现类继承此接口即可。
例如:
feign接口定义如下
@FeignClient(ProviderApiAutoConfig.PLACE_HOLD_SERVICE_NAME)
public interface ProductService {
// 为了让spring mvc能够正确绑定变量
public class Page extends PageRequest {
}
@RequestMapping(value = "/{version}/pt/product", method = RequestMethod.POST)
Response insert(@RequestBody Product product);
}
service实现类方法参数必须再写一次@RequestBody注解,方法