场景
接前一篇《spring-cloud微服务部署-feign服务间调用》,有时候需要单体整包部署,新建一个模块mono,这里面只需要写一个启动类,然后service-a和service-b里面的bean都是一起扫描启动了,就是一个单体项目了,但是之前定义了feign接口,里面service-a调用了service-b的hello方法,这个时候需要做一些处理,否则feign调用不到方法,需要使用本地直连的方式改造,不改动项目之前的架构,只需通过application.yml里面的配置,就可以同时支持微服务单独部署或者单体整包部署。
单体模块
在pom.xml中引入依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.smant.xhappy</groupId>
<artifactId>service-a</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.smant.xhappy</groupId>
<artifactId>service-b</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.smant.xhappy</groupId>
<artifactId>service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
</dependencies>
写一个启动类,可以看到在@ComponentScan注解配置了excludeFilters,这里面配置了排除@MonoExclude这个注解标记的bean:
@EnableFeignClients("com.smant.xhappy.api")
@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = MonoExclude.class))
@SpringBootApplication(scanBasePackages = "com.smant.xhappy")
public class MonoApp {
public static void main(String[] args) {
System.out.println("MonoApp.......................");
SpringApplication.run(MonoApp.class, args);
}
}
排除service-a和service-b里面的启动类(如果不排除,feign重复定义接口会报错),这里使用注解的方式排除:
在上一篇可能看到这个注解,加上这个注解以后,希望springboot在扫描的时候不要扫描进去。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MonoExclude {
String value() default "";
}
修改feign接口定义,指定url,当url写了地址,则feign会直接请求这个地址,不会经过注册中心了;如果url没有配置,则会通过nacos注册中心查找服务的url。
这个时候原来feign的调用实际上就是本地接口调用本地的另一个接口,微服务部署时是一个地址的接口调用另一个地址的接口。虽然这种方式比纯单体项目多绕了一次,纯单体项目直接注入service,然后调用方法就可以了,但是为了兼容两种模式,总得有个取舍,本地发一次http调用几乎对性能没什么影响,想想微服务调用的时候,不同地址之间发请求都可以接受。
在application.yml加入配置:
server:
port: 8888
spring:
application:
name: mono
cloud:
nacos:
discovery:
enabled: false
logging:
level:
root: INFO
serviceb:
url: http://localhost:8888
总结
在单体部署的时候,由于之前是微服务的架构,为了不改变原来的微服务架构,引入一个新的单体模块用来单体部署。虽然这个时候所有的bean都在一起启动了,但是原来service-a里面通过feign调用service-b的接口的逻辑并没有修改,如果是纯单体项目,直接注入service-b里面写service就直接调用方法了,但是为了不破坏原来的微服务结构,不改动其他模块代码的情况下,就可以通过feign框架的调用逻辑来处理。
只需要在feign定义接口的时候,通过配置url参数,在单体的时候配置url,feign直连url发请求;微服务的时候不需要配置url,feign通过nacos获取url然后发请求。