Java 微服务实用指南(一)

本文将为大家介绍什么是 Java 微服务 , 了解 Java 微服务的体系架构 , 以及如何设计、开发、部署和测试 。
Java 微服务:基础要真正理解 Java 微服务 , 就必须从最基本的东西开始:为人诟病的 Java 大型独体应用 , 它是什么 , 它的优点和缺点是什么 。
什么是 Java 大型独体应用?假设你正在为一家银行或一家金融科技初创公司工作 。 你为用户提供一款可以用它来开设新的银行账户的移动应用程序 。
如果用 Java 代码来写 , 可以实现一个简化版的控制器类 , 如下所示 。
复制代码
@Controllerclass BankController {@PostMapping("/users/register")public void register(RegistrationForm form) {validate(form);riskCheck(form);openBankAccount(form);// 略……}}这段代码要:

  1. 验证注册表单 。
  2. 对用户的地址进行风险检查 , 以决定是否可以给他一个银行帐户 。
  3. 打开这个银行账户
部署的时候 , 你会将 BankController 类与所有其他源代码一起打包到 bank.jar 或 bank.war 中:在远古时期 , 这个庞然大物还是不错的 , 它包含你的银行系统运行所需的所有代码 。 (粗略估算 , 一开始你的 jar 或 war 文件的大小会在 1-100MB 范围之内 。 )
然后在服务器上运行.jar 文件——这就是部署 Java 应用程序所需要做的全部工作 。
Java 微服务实用指南(一)文章插图
Java 大型独体应用存在什么问题?本质上 , Java 大型独体应用没有什么问题 。 但通过以往的项目经验 , 我们可以明显发现 , 如果你:
  1. 让许多不同的程序员 / 团队 / 顾问……
  2. 面临着高压和不明确需求 , 围绕同一款大型独体应用工作……
  3. 好几年……
那么你那个小小的 bank.jar 文件就会变成一只巨大的、有千兆字节的代码怪物 , 每个人都不敢部署它 。
如何让 Java 大型独体应用变得更小?这自然就引出了如何缩小大型独体应用的问题 。 现在 , 你的 bank.jar 是在一个 JVM 中运行的 , 一 台服务器上运行一个进程 。 不多也不少 。
现在 , 你可能会产生一个想法:那个风险检查服务是公司其他部门使用的 , 我的这款银行应用与它没什么关系 , 不妨把它切离出去 , 将它作为自己的产品去部署 , 作为单独的进程来运行 。
什么是 Java 微服务?实际上 , 这意味着你不需要在你的 BankController 中调用 riskCheck() 方法 , 而是将该方法或 bean 及其所有辅助类移动到它自己的 Maven/Gradle 项目中 , 对其进行源代码配置管理 , 并将其独立部署 , 不依赖于你的银行系统 。
整个提取过程本身会不会使你新的 RiskCheck 模块成为微服务呢 , 大家对微服务定义有着不同的解释:
  • 如果它里面只有 5-7 个类 , 那么算不算微?
  • 100 或者 1000 个类仍然算是微吗?
  • 这和类的数量有什么关系吗?
我们不去钻理论上的牛角尖 , 而是关注其实用性 , 做以下两件事:
  1. 调用所有可单独部署的服务(即与大小或领域边界无关的微服务) 。
  2. 重点关注服务间的通信这一重要主题 , 因为你的微服务需要相互通信的方式 。
所以 , 总结一下:你之前拥有一个 JVM 进程 , 即一个银行大型独体应用 。 现在 , 除了这个银行 JVM 进程 , 还有一个在自己 JVM 进程中运行的 RiskCheck 微服务 。 你的大型独体应用现在必须调用这个微服务进行风险检查 。
怎么做呢?
如何在 Java 微服务之间进行通信?基本上 , 有两种选择:同步通信或异步通信 。
(http)/rest(同步通信)
同步微服务通信通常通过 HTTP 和返回 XML 或 JSON 的类似 rest 的服务来完成——尽管这不是必需的 (例如 , 参考谷歌的协议缓冲区) 。
如果你需要立即响应 , 可以使用 REST 通信 , 具体到我们的案例就是这样做的 , 因为在开户之前必须进行风险检查:不做风险检查 , 就不给开户 。
在工具方面 , 可以看看哪些类库最适合同步 Java REST 调用 。
消息传递(异步通信)
异步微服务通信通常通过 JMS 实现和 / 或 AMQP 等协议的消息传递来完成 。 通常 , 是因为实际上如 email/smtp 驱动集成的数量是不可低估的 。
有时 , 使用一个微服务并不需要得到立即响应 , 比如用户按下“立即购买”按钮并希望生成发票 , 则当然不必在用户购买这一请求 / 响应周期内完成 。
在工具方面 , 可以看看哪些代理最适合异步 Java 消息传递 。
示例:在 Java 中调用 REST API假设我们选择使用同步微服务通信 , 那么我们上面的 Java 代码看起来就像是更底层的代码 。 因为对于微服务通信 , 通常会创建 client 类库 , 将实际的 HTTP 调用抽象出来 。