RPC(remote produce call远程过程调用)与HTTP
RPC:类似的还有RMI,底层都是基于原生TCP(传输控制协议)通信,速度快,效率高,但灵活性低,限定技术,语言, 早期的webservice,现在热门的dubbo(阿里开发的),都是基于rpc。
HTTP:基于TCP,但规定了数据的传输格式,缺点:消息封装臃肿,效率较低。优点:对服务提供的调用方法没有任何的技术限定,自由灵活,更符合微服务的概念。rest风格就是HTTP实现的。
基于http的spring模板工具类RestTemplate
用处:实现跨服务的调用通过resttemplate调用url 与类对象。分布式服务
resttemplate模板工具类目前支持三种客户端工具:
1、Httpclient
2、OkHttp
3、JDK原生的HttpurlConnection(默认)
上源码:
//在调用者的启动器里面添加RestTemplate
@SpringBootApplication
public class ConsumerApplication {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();//使用默认的http客户端工具
}
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
在控制器里通过resttemplate调用其他服务的处理结果,实现了服务之间的调用,下面的url是被调用服务的url地址,结果返回为User。
源码位于我的github:https://github.com/zhudinghuan/Remote-Procedure-Call-Protocol 有兴趣可以看看。
@Controller
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@ResponseBody
@RequestMapping("hello")
private User query(){
String url="http://localhost:8081/hello";
User user=restTemplate.getForObject(url,User.class);
return user;
}
}
springcloud简介
springcloud将目前非常流行的一些技术整合在一起,实现了诸如:配置管理,服务发现,智能路由,负载均衡,熔断器,控制总线,集群状态等功能。
主要包括以下组件:
Eureka注册中心管理服务
利用resttemplate写死需要调用的服务的弊端:
1、url地址写在代码里不方便后期修改‘
2、如果被调用的服务宕机,调用者无法感知
3、无法做到负载均衡
eureka原理图:
逻辑过程:
运行起来的每一个服务都会向注册中心进行注册,提交自己的服务名,地址,以及实例对象,并且在设置时间间隔内进行续约,更新状态,已经挂掉的服务会被剔除,保证服务的有效性。在调用时,服务调用者通过拉取注册中心的服务列表,获得服务的基本信息,再通过url进行调用。
第一种方式:不实现负载均衡的方式实现通过注册中心进行调用
在搭建好注册中心以及注册好服务之后,可以通过注入DiscoveryClient discoveryClient,实现对注册中心数据的拉取,实现通过注册中心来调用服务。具体代码如下:
package com.example.consumeservice.Controller;
import com.example.consumeservice.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@Controller
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@RequestMapping("hello")
@ResponseBody
private User query(){
//通过名称拉取注册列表
List<ServiceInstance> list=discoveryClient.getInstances("USER-SERVER");
//第一个服务
ServiceInstance instanceInfo=list.get(0);
String url="http://"+instanceInfo.getHost()+":"+instanceInfo.getPort()+"/hello";
User user=restTemplate.getForObject(url,User.class);
return user;
}
}
注意:
在注入DiscoveryClient时,是注入import org.springframework.cloud.client.discovery.DiscoveryClient这个包下的
第二种方式:实现负载均衡的方式实现通过注册中心进行调用?
负载均衡是什么
负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。
怎样实现?
1、随机
2、轮询
3、hash
我们通过ribbon实现负载均衡,因为它内置负载均衡算法。
第一步pom文件
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
第二步加注解(在resttemplate上面添加 @LoadBalanced)
package com.example.consumeservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
//import org.springframework.web.client.RestTemplate;
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumeServiceApplication {
@Bean
@LoadBalanced
//内置拦截器,拦截resttemplate请求
public RestTemplate restTemplate(){
return new RestTemplate();//使用默认的http客户端工具
}
public static void main(String[] args) {
SpringApplication.run(ConsumeServiceApplication.class, args);
}
}
第三步使用
默认采用轮询的方式,采用其他方法改yml
private User query(){
//用服务名称USER-SERVER直接取代主机号加端口
String url="http://USER-SERVER/hello";
User user=restTemplate.getForObject(url,User.class);
return user;
}