弄浪的鱼

开始系统学习微服务相关的知识点,现在微服务中的主流框架是 Spring Cloud 和 Dubbo,因为公司用的是 Spring Cloud,我就从 Spring Cloud 着手实战微服务。

先来看两个服务之间的调用,Spring Boot 是怎么帮我们做的?存在什么弊端?要如何解决?

RestTemplate

Spring Boot 在 org.springframework.web.client.RestTemplate 中提供了 RestTemplate 能够帮助我们调用 Restful 形式的服务接口。

先看一下项目结构:

1
2
3
4
.
├── microcloud-consumer # 服务消费者
├── microcloud-provider # 服务提供者
└── pom.xml # 父pom统一管理版本等

microcloud-provider

服务提供者的配置如下所示,端口为 7900,并且给一个别名 microcloud-provider。

1
2
3
4
5
server:
port: 7900
spring:
application:
name: microcloud-provider

它提供了一个 Rest 接口

1
2
3
4
5
6
7
8
@RestController
public class UserController {

@GetMapping("/user/{id}")
public User getUser(@PathVariable(value = "id") String id){
return new User(id);
}
}

访问 http://localhost:7900/user/1 返回 {“id”:”1”,”name”:null}。

microcloud-consumer

现在 Consumer 要想办法调用 Provider 提供的接口,配置文件和 Controller 如下:

1
2
3
4
5
server:
port: 8900
spring:
application:
name: micro-consumer

Spring Boot 提供了 RestTemplate 帮助我们调用 Rest 的接口。

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
public class OrderController {

@Autowired
private RestTemplate restTemplate;

@GetMapping("/order/{id}")
public User getCustomer(@PathVariable("id") String id){
User user = restTemplate.getForObject("http://localhost:7900/user/" + id, User.class);
return user;
}
}

RestTemplate 需要实例化,然后作为 Bean 交给 Spring 管理才能注入。

1
2
3
4
5
6
7
8
9
10
11
@SpringBootApplication
public class ConsumerApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class, args);
}

@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

这样调用由什么问题?

我们的调用主要使用了这个方法 restTemplate.getForObject("http://localhost:7900/user/" + id, User.class); ,其中需要提供服务提供者的 URL 路径。

这样就有问题了,这个路径是写死的,服务是固定的,更换不方便,即使我将路径方法配置文件中,任然不方便。

1
2
3
4
5
6
7
server:
port: 8900
spring:
application:
name: micro-consumer
user:
usr: http://localhost:7900/user/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RestController
public class OrderController {

@Autowired
private RestTemplate restTemplate;

@Value("${user.url}")
private String url;

@GetMapping("/order/{id}")
public User getCustomer(@PathVariable("id") String id){
// User user = restTemplate.getForObject("http://localhost:7900/user/" + id, User.class);
User user = restTemplate.getForObject(url + id, User.class);
return user;
}
}

怎么样的方式更方便的呢?就是使用服务注册与发现方法,下篇文章就讲如何用 Eureka 实现服务的注册与发现,并对现有的项目进行改造。