方式一:RestTemplate
1.RestTemplate简述
RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求等。RestTemplate 继承自 InterceptingHttpAccessor 并且实现了 RestOperations 接口,其中 RestOperations 接口定义了基本的 Restful 操作,因此RestTemplate也支持restful风格请求
1.1 服务调用代码实现
背景: provider提供服务为服务端. consumer调用服务端为消费端
- provider提供doSomething方法
@GetMapping("/provider/{string}")
public String doSomething(@PathVariable String string) {
return "provider:Hello "+string;
}
- consumer调用provider的方法
@Autowired
private RestTemplate restTemplate;
@GetMapping("/consumer")
public String doSomething() {
String name="kris"
//定义服务提供方的地址
String url = "http://localhost:8081/provider/"+name;
//调用服务提供方(sca-provider)
return restTemplate.getForObject(url, String.class);
打开provider和consumer的启动项后,访问http://localhost:8082/consumer ,调用成功则返回结果"provider:Hello kirs"
注:如果只关注服务返回的数据则使用getForObject若要定义响应头相关信息则推荐使用getForEntity
1.2 调用的负载均衡
当开发者想要实现服负载均衡时,则有如下两种实现方案
1.2.1 RestTempalte+ LoadBalanceClient
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("/consumer2")
public String doSomething2() {
String name="kris"
// 根据服务名serviceId,返回一个服务实例
ServiceInstance serviceInstance = loadBalancerClient.choose("provider");
//拼接url,
String url = String.format("http://%s:%s/provider/%s",
serviceInstance.getHost(),
serviceInstance.getPort(),
Name);
//显示每次访问,端口的变化
System.out.println("request url:" + url);
return restTemplate.getForObject(url, String.class);
}
启动多台procvider时,loadBalancerClient可以动态的调用服务底层是基于Ribbon实现的,默认的规则为轮询机制
1.2.2 RestTempalte+@LoadBalanced
此外我们可以直接通过@LoadBalanced注解的方式来实现负载均衡
- 配置一个restTemplate交给spring容器
@Bean
@LoadBalanced
public RestTemplate loadBalancedRestTemplate() {
return new RestTemplate();
}
- 在需要使用负载均衡的地方经行依赖注入
@Autowired
private RestTemplate loadBalancedRestTemplate;
- 业务的实现
@GetMapping("/consumer3")
public String doSomething3(){
String name="kris"
String url=String.format("http://%s/provider/%s",
"provider",Name);
//向服务提供方发起http请求,获取响应数据
return loadBalancedRestTemplate.getForObject(
url,//要请求的服务的地址
String.class);//String.class为请求服务的响应结果类型
}
方式二:Feign
1 简述Feign
Feign是一种声明式web服务客户端, 底层封装了rest技术, 通过feign可以简化消费方对远程服务的调用,
通过注解+接口,完成服务的简单调用.
那么我们如何再spring cloud项目中使用呢?
2.代码实现
- 1.消费方添加项目依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
- 2 启动类添加注解@EnableFeignClients
@EnableFeignClients
@SpringBootApplication
public class ConsumerApplication {…}
- 3 定义接口
@FeignClient(value="provider")// value映射服务提供名子
public interface RemoteProviderService {
@GetMapping("/provider/{msg}")//与要调用的服务提供端名字一致
String doSomething(@PathVariable("msg") String msg);//注解名要和路径定义名一致
}
//@FeignClient 描述的接口会被动态代理创建实现类
4.controller 中调用feign
@RestController
@RequestMapping("consumer")
public class FeignConsumerController {
@Autowired
private RemoteProviderService remoteProviderService;
@RequestMapping("{msg}")
public String doSomething(@PathVariable String msg) {
return remoteProviderService.doSomething(msg);
}
}
3 Feign的远程调用原理
小结 :
- 项目启动后 @EnableFeignCleints 注解告诉springcloud,启动 Feign Starter 组件.
- Feign Starter 在项目启动过程中注册全局配置,并扫描包下所由@FeignClient注解描述的接口,然后由系统底层创建接口实现类(JDK代理类),注册 IOC 容器。
- 接口调用时被动态代理类逻辑拦截,将 @FeignClient 请求信息通过编码器生成 Request对象,基于此对象进行远程过程调用。
- Request对象经Ribbon进行负载均衡,挑选出一个健康的 Server 实例
- 通过Client 携带 Request 调用远端服务返回请求响应。
- 通过解码器生成 Response 返回客户端,将信息流解析成为接口返回数据。