微服务之间是通过RPC来交互的。
Eureka server和client 的jar包 都会引用一个 ribbon 包和httpclient包,显然Eureka是通过httpclient来进行通信的。
我们需要服务与服务之间进行通信,至少得有2个服务才能看出效果(自己和自己通信的别闹)。
所以我们从会员服务copy出一个订单服务。
pom.xml 是一样的(除了项目名artifactId、name),
application.yml 里面我将端口号改成了8121(每个服务隔个10),服务别名改成:app-order
启动类还是一样(就改了类名),但是controller我贴一下
package com.study.api.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class OrderController{
/**
* RestTemplate 是由SpringBoot Web 提供的 ,默认整合ribbon负载均衡器
* rest 方式底层是采用httpclient 技术
*/
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/getOrder")
public String getOrder(){
String url = "http://localhost:8110/getMember";
String result = restTemplate.getForObject(url,String.class);
System.out.println("订单服务调用会员服务:"+result);
return result;
}
}
我们在getOrder中尝试使用RestTemplate来调用会员服务。
然后启动就会报错
***************************
APPLICATION FAILED TO START
***************************
Description:
Field restTemplate in com.study.api.controller.OrderController required a bean of type 'org.springframework.web.client.RestTemplate' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.web.client.RestTemplate' in your configuration.
这其实是因为RestTemplate 默认是没有在spring 容器中的,所以无法通过Autowired来获取实例,
我们需要在启动类中将它加到spring容器中,在启动类加上
package com.study.api.controller;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableEurekaClient
public class AppOrder {
public static void main(String[] args){
SpringApplication.run(AppOrder.class,args);
}
@Bean // 解决RestTemplate 找不到,将其添加到spring容器
RestTemplate restTemplate(){
return new RestTemplate();
}
}
再启动的时候就可以用之前那个方式去访问getOrder了,当然,它调用了getMember,所以我们看到的是getMember的结果。
但是我们在getOrder() 方法中直接写会员服务的地址了,这样还要eureka有个屁用。
所以我们要改成通过服务别名来进行服务间的通信。getOrder方法改成如下
@RequestMapping("/getOrder")
public String getOrder(){
String url = "http://app-member/getMember";
String result = restTemplate.getForObject(url,String.class);
System.out.println("订单服务调用会员服务:"+result);
return result;
}
重启再访问是这个样子
服务器500,报的是java.net.UnknownHostException: app-member
其实是因为我们没有开启 rest 别名访问 的支持,我们在注册RestTemplate的时候加上@LoadBalanced 来开启对 rest 别名访问的支持
@Bean // 解决RestTemplate 找不到,将其添加到spring容器
@LoadBalanced // 如果需要使用rest方式以别名方式进行调用ribbon负载均衡器,默认为轮询方式
RestTemplate restTemplate(){
return new RestTemplate();
}
加了这个注解之后会调用ribbon负载均衡器,重启后就可以通过别名来访问了
因为开启了负载均衡,所以我们可以通过使用相同项目别名的方式来达到集群的效果。
假如我有一台服务器用别名app-member注册到eureka,然后另一台服务器也以别名注册到eureka,
当我们通过别名进行服务间调用时,eureka就会根据负载均衡的策略(默认是轮训)来分配最终调用的服务器。
集群的时候可以在eureka里看到有几个叶子节点。