springCloud 服务间的两种通信方式
一、springCloud 服务间的通信方式有两种
- RestTemplate 方式
- Feign 的方式
二、RestTemplate 方式
RestTemplate 中也分为三种方式
简单来演示一下吧
第一种方式
直接使用 RestTemplate ,url 写死服务端编写
/* 用来测试与 order 服务的连接 @author ccyang @date 2018/7/1 16:06 */
@RestController
public class serverController {@GetMapping("/getMsg")
public String getMsg(){
return "this is product' msg";
}
}
客户端编写
/** * @author ccyang * @date 2018/7/1 16:13 */
@RestController
@Slf4j
public class clientController {
@GetMapping("/getProductMsg")
public String getProductMsg(){
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject("http://localhost:8080/getMsg",String.class);
log.info("response = {}" , response);
return response;
}
}
然后去访问 http://localhost:8080/getMsg 即可。
因为服务端的 api 被硬编码在客户端,因此有两个缺点:
– 当注册中心有很多服务时,我们可能不知道我们需要的服务由谁提供、api是多少,因此就可能无法调用到服务。
–当某个服务部署了多个,例如 api 是: “localhost:9080/getMsg,localhost:9081/getMsg “,那么此时就需要负载均衡,这种硬编码显然不符合场景。
第二种方式:
service端代码依旧,客户端通过 LoadBalancerClient 来获取应用名,进而获取地址和端口,在格式化拼接地址,从而调用 product服务。如下:/* 测试获取 product服务的msg @author ccyang @date 2018/7/1 16:13 */
@RestController
@Slf4j
public class clientController {@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("/getProductMsg")
public String getProductMsg(){
RestTemplate restTemplate = new RestTemplate();
ServiceInstance serviceInstance = loadBalancerClient.choose("PRODUCT"); // serviceId 为提供服务的应用名
String url = String.format("http://%s:%s",serviceInstance.getHost(),serviceInstance.getPort() + "/getMsg");
String response = restTemplate.getForObject( url, String.class);
log.info("response = {}" , response);
return response;
}
}
缺点是每次调用服务都要这样写,编码很麻烦。
第三种方式
通过 @LoadBalanced,可在restTemplate 直接使用应用名字。@Component
public class RestTemplateConfig {@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
@RestController
@Slf4j
public class clientController {@Autowired
private RestTemplate restTemplate;
@GetMapping("/getProductMsg")
public String getProductMsg(){
String response = restTemplate.getForObject( "http://PRODUCT/getMsg", String.class); // 通过应用名进行访问
log.info("response = {}" , response);
return response;
}
}
三、使用 Feign 的方式进行通信
- 声明式 REST客户端(伪 RPC)
- 采用了基于接口的注解
先看看如何使用 Feign:
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId >
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.4.RELEASE</version>
</dependency>
添加注解到主类上
@EnableFeignClients
定义要调用的接口
@FeignClient(name = “product”) // 服务名
public interface ProductClient {@GetMapping(“/getMsg”) // 这里要和 Product服务提供的接口一致
String productMsg();}
在该使用的地方使用注解中提供的方法
@RestController
@Slf4j
public class clientController {@Autowired
private ProductClient productClient; // 有报错,不影响
@GetMapping(“/getProductMsg”)
public String getProductMsg(){String response = productClient.productMsg();
log.info("response = {}" , response);
return response;
}
}
Feign 可以看做是一个伪 RPC,而且HTTP远程调用对开发者完全透明。
RestTemplate 内部使用 Ribbon做负载均衡
Feign 内部也是使用的Ribbon做负载均衡
还没有评论,来说两句吧...