RPC:Remote Produce Call远程过程调用,类似的还有RMI。自定义数据格式,基于原生TCP通信,速度快,效率高。早期的webservice,现在热门的dubbo,都是RPC的典型代表
Http:http其实是一种网络传输协议,基于TCP,规定了数据传输的格式。现在客户端浏览器与服务端通信基本都是采用Http协议,也可以用来进行远程服务调用。缺点是消息封装臃肿,优势是对服务的提供和调用方没有任何技术限定,自由灵活,更符合微服务理念。
现在热门的Rest风格,就可以通过http协议来实现。
Spring提供了一个RestTemplate模板工具类,对基于Http的客户端进行了封装,并且实现了对象与json的序列化和反序列化,非常方便
@SpringBootApplication
public class HttpDemoApplication {
public static void main(String[] args) {
SpringApplication.run(HttpDemoApplication.class, args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@RunWith(SpringRunner.class)
@SpringBootTest(classes = HttpDemoApplication.class)
public class HttpDemoApplicationTests {
@Autowired
private RestTemplate restTemplate;
@Test
public void httpGet() {// 调用springboot案例中的rest接口
User user = this.restTemplate.getForObject("http://localhost/user/1",
User.class);
System.out.println(user);
}
}
注册写入引导类中,保证RestTemplate一定会被注册放入spring容器。
Eureka负责管理、记录服务提供者的信息。服务调用者无需自己寻找服务,而是把自己的需求告诉Eureka,然后Eureka会把符合需求的服务返回。
服务提供方与Eureka之间通过 “心跳” 机制进行监控,当某个服务提供方出现问题,Eureka自然会把它从服务列表中剔除。这就实现了服务的自动注册、发现、状态监控。
server:
port: 10086 # 端口
spring:
application:
name: eureka-server # 应用名称,会在Eureka中显示
eureka:
client:
service-url: # EurekaServer的地址,现在是自己的地址,如果是集群,需要加上其它Server的地址。
defaultZone: http://127.0.0.1:${server.port}/eureka
引导类:
@SpringBootApplication
@EnableEurekaServer // 声明当前springboot应用是一个eureka服务中心
public class ItcastEurekaApplication {
public static void main(String[] args) {
SpringApplication.run(ItcastEurekaApplication.class, args);
}
}
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Finchley.SR2version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
server:
port: 8081
spring:
datasource:
url: jdbc:mysql://localhost:3306/heima
username: root
password: root
driverClassName: com.mysql.jdbc.Driver
application:
name: service-provider # 应用名称,注册到eureka后的服务名称
mybatis:
type-aliases-package: cn.itcast.service.pojo
eureka:
client:
service-url: # EurekaServer地址
defaultZone: http://127.0.0.1:10086/eureka
@SpringBootApplication
@EnableDiscoveryClient
public class ItcastServiceProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ItcastServiceApplication.class, args);
}
}
通过添加 @EnableDiscoveryClient 来开启Eureka客户端功能
将消费方注册到Eureka,启动类配置开启Eureka客户端,yml说明eureka客户端
@Controller
@RequestMapping("consumer/user")
public class UserController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient; // eureka客户端,可以获取到eureka中服务的信息
@GetMapping
@ResponseBody
public User queryUserById(@RequestParam("id") Long id){
// 根据服务名称,获取服务实例。有可能是集群,所以是service实例集合
List<ServiceInstance> instances = discoveryClient.getInstances("service-provider");
// 因为只有一个Service-provider。所以获取第一个实例
ServiceInstance instance = instances.get(0);
// 获取ip和端口信息,拼接成服务地址
String baseUrl = "http://" + instance.getHost() + ":" +
instance.getPort() + "/user/" + id;
User user = this.restTemplate.getForObject(baseUrl, User.class);
return user;
}
将一个a的url注册到b的yml中,集群中的erueka会交换信息,只用注册一次。
server:
port: 10086 # 端口
spring:
application:
name: eureka-server # 应用名称,会在Eureka中显示
eureka:
client:
service-url: # 配置其他Eureka服务的地址,而不是自己,比如10087
defaultZone: http://127.0.0.1:10087/eureka
Eureka中已经集成了Ribbon,所以我们无需引入新的依赖,直接修改代码。
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
启动类注册resttemplate时,直接加上@LoadBalanced开启
@Controller
@RequestMapping("consumer/user")
public class UserController {
@Autowired
private RestTemplate restTemplate;
//@Autowired
//private DiscoveryClient discoveryClient; // 注入discoveryClient,通过该客户端获取服务列表
@GetMapping
@ResponseBody
public User queryUserById(@RequestParam("id") Long id){
// 通过client获取服务提供方的服务列表,这里我们只有一个
// ServiceInstance instance = discoveryClient.getInstances("service-provider").get(0);
String baseUrl = "http://service-provider/user/" + id;
User user = this.restTemplate.getForObject(baseUrl, User.class);
return user;
}
}
@Autowired
private RestTemplate restTemplate;
由于 RestTemplate 在注册时开启了负载均衡,所以可以自动去寻找服务链接,不需要手动获取。