其中 Ribbon 是基于 HTTP 和 TCP 客户端的负载均衡器,restTemplate 是 Spring 提供的 Restful 远程调用的模板,两者结合就可以达到远程调用的负载均衡。
而 Feign 是一个更加声明式的 HTTP 客户端,开发者可以像调用本地方法一样调用它,完全感觉不到是远程调用,结合 Ribbon 也可以做负载均衡。
既然两个问题都得到了解决,我们就用一个例子来进一步说明一下,例子包含了微服务中最基本的三个角色(注册中心、服务提供者、服务消费者):
注册中心
注解 @EnableEurekaServer 表示该 Spring Boot 应用是一个注册中心。
@EnableEurekaServer
@SpringBootApplication
public class EurekaserverApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaserverApplication.class,
args);
}
}
eureka.client.registerWithEureka: false 和fetchRegistry: false 来表明自己是一个 eureka server。
server:
port: 8080
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
service-hello 服务
注解 @EnableEurekaClient 表示他是一个 Eureka 客户端,它会在注册中心注册自己。
注解 @RestController 表示这是一个控制器,@RequestMapping("/hello") 表示匹配到请求 \'/hello\' 时会调用该方法进行响应。
@SpringBootApplication
@EnableEurekaClient
@RestController
public class ServiceHelloApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceHelloApplication.class,
args);
}
@Value("${server.port}")
String port;
@RequestMapping("/hello")
public String home(@RequestParam String name)
{
return "hello "+name+",i am from
port:" +port;
}
}
注册中心的地址为 :8080/eureka/,也就是上面我们定义的。服务名为 service-hello,将会被调用者使用。
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8080/eureka/
server:
port: 8081
spring:
application:
name: service-hello
服务消费者 service-ribbon
假设 service-ribbon 端口为 8082,当我们访问 :8080/hello 时,HelloControler 接收到请求,并调用 HelloService 中的 helloService 方法,HelloService 中通过定义的 restTemplate 去调用 。此处要注意的是 @LoadBalanced 注解,它表示启用负载均衡。
@SpringBootApplication
@EnableDiscoveryClient
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRibbonApplication.class,
args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
public String helloService(String name) {
return restTemplate.getForObject("http://service-hello/hello?name="+name,String.class);
}
}
@RestController
public class HelloControler {
@Autowired
HelloService helloService;
@RequestMapping(value = "/hello")
public String hello(@RequestParam String name){
return helloService.helloService(name);
}
}
至此其实一个微服务应用的雏形已经搭建出来了,服务治理、服务调用可以说是「五脏六腑」中的「心脏」。
心脏的依托