概述
像HSF、dubbo这种RPC框架,客户端都是通过接口(Interface)调用服务的,无须自己拼装调用方式,客户端就像调用本地类方法一样。而spring cloud原生的客户端调用时通过RestTemplate发起Http调用请求,需要手动指定URL和参数,在使用上比较费劲,后来出现了申明式服务调用——Spring Cloud Feign,终于使调用得到了解放,而本文就是讲述如何极致地利用Feign来进行微服务开发,如何定义代码结构规范。
RestTemplate
RestTemplate 可以认为就是对HttpClient的一个封装,可以把调用的结果转化成Java 对象,从而达到简化开发的目的。
下面简单用一个例子来说明一下(例子实际设计到了eureka注册中心,关于如何使用eureka注册中心这些可以自己查阅相关资料,这里忽略)。在服务器端,我们像正常开发Controller一样写一个hi的方法,返回一个简单的字符串。
然后在客户端,显示需要注册一个RestTemplate Bean,这里@LoadBalanced的注解就是开启客户端负载均衡的能力(前提还需要在入口类上添加@EnableDiscoveryClient注解开启服务发现)
然后就像http请求一样调用服务器的hi方法,然后得到返回结果。例子中的equipment-service 是服务Id(serviceId),实际调用时会根据服务发现的结果替换成服务的ip和端口号。
可以看出,这种直接拼链接的调用对于微服务开发很不友好,所以才有了Feign的诞生。
申明式服务调用:Spring Cloud Feign
还是刚才的例子,在服务器端写个hi方法:
剩下的就是客户端的事情了。
首先,客户端需要引入Feign(这里也只是简要说一下流程)
然后定义一个interface。这个接口是什么意思呢?它实际就是把RestTemplate调用的链接转成了接口和方法。如URL中的equipment-service放到了interface的@FeignClient注解里面,而URL的路径对应方法上的@RequestMapping,URL参数也对应方法的参数,通过这种方式,巧妙地把URL调用转化成了方法的调用。
定义好接口后,Feign在spring初始化的时候会自动扫描包含@FeignClient的接口并注册成spring bean,然后就可以直接使用了
Feign 的接口定义移到服务器端
上面的代码接口是在客户端定义的,无形中客户端多了这一块麻烦的工作,而比较合理的做法是由服务提供者来提供接口。
首先在服务端定义接口
然后服务器端新建一个Controller(注意是Controller)继承这个接口。
最后客户端只需引入这个接口,就像本地spring bean一样调用服务了,客户端是不用关系服务在哪台服务上面的。
微服务代码结构规范
在上面接口调用的基础上,我们可以总结出一套代码结构规范。
1、首先所有的微服务有一个根级的root pom,包含了spring cloud的版本等基本定义信息,同时也定义好统一的groupId。这个pom文件最大的好处就是统一了spring
cloud的版本,避免以后开发中出现的各种不兼容问题。
这个pom定义好后一般不轻易改变,如果接入新版本的spring cloud,则升级maven version再deploy到maven服务器即可。
<parent>
<groupId>com.cehome.cloud</groupId>
<artifactId>cehome-cloud-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
2、和root pom同目录下是各种微服务目录(项目),每种微服务为一个项目,每个项目下面再分为api(接口)和service(实现)模块。
3.一个服务开发的流程是这样的:
服务器端:在api模块定义服务接口,在service模块实现服务。
客户端:直接依赖api jar包即可调用服务,无须了解调用服务器地址和具体的URL。
例如对于user微服务,服务器端由user-api 和user-service两个模块,开发完后,user-api发布到maven服务器成user-api-1.0.0.jar;
客户端直接依赖user-api-1.0.0.jar,引用服务接口就可以调用服务。
注意user-api-1.0.0.jar是一个非常轻量级的jar包,只包含了interface和一些实体类定义,一般不会有微服务实现的代码逻辑。