服務調用有兩種方式:
A.使用RestTemplate 進行服務調用 查看
B.使用Feign 進行聲明式服務調用
上一次寫了使用RestTemplate的方式,這次使用Feign的方式實現
服務注冊發現中心使用nacos
啟動nacos
spring boot 版本 2.2.1.RELEASE
1.服務端
provider
(1)添加依賴
<properties> <java.version>1.8</java.version> <nacos.version>2.1.1.RELEASE</nacos.version> <spring-cloud.version>Greenwich.SR3</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>${nacos.version}</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
(2)修改配置
server.port=8010 spring.application.name=service-provider spring.cloud.nacos.discovery.enabled=true spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 spring.cloud.nacos.discovery.service=${spring.application.name} management.endpoints.web.exposure.include=* management.endpoint.health.show-details=always
(3)測試方法
package com.xyz.provider.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class demoController { @RequestMapping("/hello") public String Hello(){ return "hello,provider"; } }
provider1
修改端口為8011
修改測試方法
package com.xyz.provider1.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class demoController { @RequestMapping("/hello") public String Hello(){ return "hello,another provider"; } }
啟動provider和provider1
2.客戶端
customer
(1)添加依賴
<properties> <java.version>1.8</java.version> <nacos.version>2.1.1.RELEASE</nacos.version> <spring-cloud.version>Greenwich.SR4</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>${nacos.version}</version> </dependency> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
(2)配置
server.port=8015 spring.application.name=service-comsumer management.endpoints.web.exposure.include=* management.endpoint.health.show-details=always spring.cloud.nacos.discovery.enabled=true spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 spring.cloud.nacos.discovery.service=${spring.application.name}
(3)修改啟動類
添加注解 @EnableFeignClients,開啟掃描Spring Cloud Feign客戶端的功能
package com.xyz.comsumer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate;
@EnableFeignClients @SpringBootApplication public class ComsumerApplication { public static void main(String[] args) { SpringApplication.run(ComsumerApplication.class, args); } }
(4)添加Feign接口
創建RemoteHelloService接口,來定義OpenFeign要調用的遠程服務接口
通過@FeginClient注解指定被調用方的服務名
通過fallback屬性指定RemoteHelloServiceFallbackFactory類,來進行遠程調用的熔斷和降級處理。
provider是要調用的服務名
說明:
添加跟調用目標方法一樣的方法聲明,必須跟目標方法的定義一致
RemoteHelloService
package com.xyz.comsumer.feign; import com.xyz.comsumer.feign.factory.RemoteHelloServiceFallbackFactory; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; @FeignClient(contextId = "remotehelloService", value = "service-provider", fallbackFactory = RemoteHelloServiceFallbackFactory.class) public interface RemoteHelloService { @GetMapping("/hello") String hello(); }
RemoteHelloServiceFallbackImpl
package com.xyz.comsumer.feign.fallback; import com.xyz.comsumer.feign.RemoteHelloService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @Component public class RemoteHelloServiceFallbackImpl implements RemoteHelloService { private final Logger logger = LoggerFactory.getLogger(RemoteHelloServiceFallbackImpl.class); private Throwable cause; @Override public String hello() { logger.error("feign 查詢信息失敗:{}", cause); return null; } public Throwable getCause() { return cause; } public void setCause(Throwable cause) { this.cause = cause; } }
RemoteHelloServiceFallbackFactory
package com.xyz.comsumer.feign.factory; import com.xyz.comsumer.feign.RemoteHelloService; import com.xyz.comsumer.feign.fallback.RemoteHelloServiceFallbackImpl; import feign.hystrix.FallbackFactory; import org.springframework.stereotype.Component; @Component public class RemoteHelloServiceFallbackFactory implements FallbackFactory<RemoteHelloService> { @Override public RemoteHelloService create(Throwable throwable) { RemoteHelloServiceFallbackImpl remoteFallback = new RemoteHelloServiceFallbackImpl(); remoteFallback.setCause(throwable); return remoteFallback; } }
要使用Feign的fallback機制,需要開啟Feign的Hystrix的功能
增加配置
feign.hystrix.enabled=true
(4)服務調用
注入剛才聲明的ProviderService,就可以像本地方法一樣進行調用了
package com.xyz.comsumer.controller; import com.xyz.comsumer.feign.RemoteHelloService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class FeignController { @Autowired RemoteHelloService remoteHelloService; @RequestMapping("feignTest") public String feignTest(){ return remoteHelloService.hello(); } }
啟動customer
訪問http://localhost:8015/call
交替返回結果
hello,provider 或 hello,another provider