服务间通信与集成
本文为阿里云容器服务Spring Cloud应用开发系列文章的第四篇。
一、在阿里云容器服务上开发Spring Cloud微服务应用
三、服务发现
四、服务间通信与集成(本文)
五、服务智能路由
六、集中配置管理
七、高可用和容错
八、监控和日志
同步通信
服务之间的通信一般采用HTTP+JSON协议,由于HTTP的开销远大于本地调用,在调用的时候一定要注意服务间API的粒度。
服务同步调用(HTTP)
在前文我们已经演示了如何利用Eureka进行服务发现。在示例代码中,foobar
服务需要通过HTTP/JSON调用foo
服务和bar
服务。Spring Cloud提供及对HTTP协议和JSON解析的支持,具体可以参见下面的代码示例:
...
@Autowired
@LoadBalanced
private RestTemplate restTemplate;
...
private BarMessage getMessageFromBarService(){
BarMessage bar = restTemplate.getForObject("http://bar/message", BarMessage.class);
log.debug("From bar service : {}.", bar);
return bar;
}
...
RestTemplate的声明需要加上@Autowired
和@LoadBalanced
两个注解。在随后对restTemplate.getForObject
的调用传入服务的URL。
http://bar/message
其中bar
服务名,/message
为希望调用的URL Path。 restTemplate.getForObject
从Eureka中获得bar
服务的所有实例,并根据内置的负载均衡算法选择一个实例调用并返回结果。
这段内容和前文介绍的服务发现和调用的内容一致,通过RestTemplate可以完成服务的发现和调用(HTTP协议)。SpringCloud提供的其它方式我们就不在这里讨论了。
WebSocket
WebSocket是一种基于TCP的轻量协议。对于交互响应要求高的应用,可以使用WebSocket协议在服务器和客户端之间进行通信,例如浏览器和服务之间的对话模式交互。在SpringCloud应用中使用WebSocket可以参见这篇文档:Using WebSocket to build an interactive web application
异步通信
异步通信机制可以将服务调用方和服务提供方解耦,基于消息或事件机制能够满足对实时性要求不特别高的场景。Spring Cloud中提供了对很多常见消息中间件的封装,例如对RabbitMQ的访问:Messaging with RabbitMQ,或者Redis访问:Messaging with Redis。
本文的示例代码中没有演示消息通信,这部分内容以后会更新。
数据库访问
build.gradle中配置对MySQL依赖
在build.gradle中添加如下内容可以将Java项目对MySQL的依赖包导入。
dependencies {
...
compile('org.springframework.boot:spring-boot-starter-data-jpa')
runtime('com.h2database:h2')
runtime('mysql:mysql-connector-java')
...
}
数据库访问代码
创建JPA访问数据库的interface,代码见foo
服务的InfoRepository.java
文件。
public interface InfoRepository extends CrudRepository<Info, Long> {
List<Info> findByName(String name);
}
在代码中通过上面定义的interface访问数据库,代码见foo
服务的FooController.java
文件:
private String getInfoFromDatabase(){
List<Info> infoList = infoRepository.findByName(KEY);
for(Info info : infoRepository.findByName(KEY)) {
return info.toString();
}
return "(no database info)";
}
对数据的初始化部分就不在这里讨论了,读者可以根据自己的实际情况选择方案。
application.yml中配置对数据库的访问
foo
的代码演示如何访问MySQL数据库,同样的代码也可以用于访问阿里云上的RDS服务。
在application.yml中配置对MySQL的访问信息。
spring:
...
datasource:
url: jdbc:mysql://mysql:3306/${{MYSQL_DATABASE}:foodb}
username: ${{MYSQL_USERNAME}:user1}
password: ${{MYSQL_PASSWORD}:passw0rd}
testWhileIdle: true
validationQuery: SELECT 1
jpa:
show-sql: false
hibernate:
ddl-auto: update
naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5Dialect
jdbc:mysql://mysql:3306/
中mysql:3306
表示访问地址为mysql的3306端口。通过docker-compose启动服务的时候,可以通过docker compose文件指定mysql所具体对应的地址,可以是一个容器化的MySQL镜像,也可以是阿里云上的RDS服务。
在Docker Compose文件中创建或指定MySQL实例
访问MySQL镜像,一般用于开发测试环境,文件为docker-compose.yml
:
mysql:
image: registry.aliyuncs.com/acs-sample/mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=passw0rd
- MYSQL_DATABASE=foodb
- MYSQL_USER=user1
- MYSQL_PASSWORD=passw0rd
foo:
image: xxx
links:
- mysql:mysql
environment:
...
- SPRING_PROFILES_ACTIVE=cloud
- MYSQL_DATABASE=foodb
- MYSQL_USERNAME=user1
- MYSQL_PASSWORD=passw0rd
docker-compose为下载registry.aliyuncs.com/acs-sample/mysql:5.7
镜像并创建一个MySQL容器,foo
通过links
将自己要访问的mysql和实际的mysql关联起来。
访问阿里云RDS
如果要访问RDS服务,则只需将mysql的image
改为external
,foo
在docker compose文件中的配置不用更改。这部分内容存在docker-compose.acs.yml:
mysql:
external:
host: ${rdsname}.mysql.rds.aliyuncs.com
port: 3306
environment:
- MYSQL_ROOT_PASSWORD=passw0rd
- MYSQL_DATABASE=foodb
- MYSQL_USER=user1
- MYSQL_PASSWORD=passw0rd
小节
本文演示了Spring Cloud应用如何利用HTTP进行同步通信,在数据库访问一节,讨论如何通过docker compose文件配置对MySQL或RDS的访问。