专栏名称: java那些事
分享java开发中常用的技术,分享软件开发中各种新技术的应用方法。每天推送java技术相关或者互联网相关文章。关注“java那些事”,让自己做一个潮流的java技术人!《java程序员由笨鸟到菜鸟》系列文章火热更新中。
目录
相关文章推荐
Java编程精选  ·  前阿里员工:内推了个38岁的研发,简历到HR ... ·  17 小时前  
芋道源码  ·  Nginx 部署负载均衡服务全解析 ·  2 天前  
芋道源码  ·  SpringBoot CORS ... ·  2 天前  
芋道源码  ·  某公司新招了个牛逼的架构师后... ·  2 天前  
51好读  ›  专栏  ›  java那些事

从 Spring Cloud 看一个微服务框架的「五脏六腑」

java那些事  · 公众号  · Java  · 2018-11-14 16:00

正文

来自:https://webfe.kujiale.com/spring-could-heart/

Spring Cloud 是一个基于 Spring Boot 实现的微服务框架,它包含了实现微服务架构所需的各种组件。

注:Spring Boot 简单理解就是简化 Spring 项目的搭建、配置、组合的框架。因为与构建微服务本身没有直接关系,所以本文不对 Spring Boot 进行展开。另外本文有一些例子涉及到 Spring 和 Spring Boot,建议先了解一下 Spring 和 Spring Boot 再阅读本文。
本文的阅读对象主要是没有接触过服务架构,想对其有一个宏观的了解的同学。

本文将从 Spring Cloud 出发,分两小节讲述微服务框架的「五脏六腑」:

  • 第一小节「服务架构」旨在说明的包括两点,一服务架构是什么及其必要性;二是服务架构的基本组成。为什么第一节写服务架构而不是微服务架构呢?原因主要是微服务架构本身与服务架构有着千丝万缕的关系,服务架构是微服务架构的根基。

  • 第二小节「五脏六腑」则将结合 Spring Cloud 这个特例来介绍一个完整的微服务框架的组成。




「服务架构」


为了方便理解,我先讲一个小故事:(改编自一知乎答主)

Martin(微服务提出者也叫 Martin)刚来到公司时是一个基层员工,它上面有经理、老板,那个时候所有人都听老板的指挥。

但是过了两年,公司的人越来越多,原来的模式下整个公司的运作效率太低,管理也很混乱。

于是已经踏上中层岗位的 Martin 建议老板进行部门划分(服务化),专门的部门只做专门的事情(单一职责)。例如研发部门只做研发,人事部门只做招聘。

老板听取了 Martin 的意见,对公司的组织架构进行了调整。

有一天,Martin 发现公司的部门越来越多,各个部门并不能完全知道对方所做的事情,这对跨部门协作(服务调用)带来了困难。

行政部门会(注册中心)来记录所有的部门,每当有新的部门行政都会记录下来(服务注册),然后公布出来让所有部门知道(服务发现)。

在新的组织架构下,公司的效率逐步提高。老板也给 Martin 发了大量奖金作为奖励,Martin 从此赢取白富美走向了人生巅峰。

这是一个公司组织架构演变的故事,主要讲的是随着公司规模的扩大,组织从集中化管理到分布化管理的过程。

映射到我们的信息系统里来也是一样的,随着我们的系统越来越复杂,变得难以管理,也有人想到去拆分然后治理。在解决复杂问题上,分治可以说是一个屡试不爽的办法。

服务化即是拆解的一种手段。而上面圆括号里面的内容其实就对应了一个服务化架构的最小组成元素,分别是服务、服务调用、注册中心、服务注册、服务发现。有了这些基本的组成要素,就可以实现一个最简单的服务架构。

面向服务的架构和微服务架构

面向服务的架构(SOA)和微服务架构是目前两种主流的服务化架构,都符合上面的例子,也有上面提到的所有组件。这两种服务架构有很多可以讲的,但是与本文的相关性不大,本文不做会过多展开,只简单介绍一下两者的区别。

准确地说微服务是去 ESB(企业服务总线)的 SOA。ESB 借鉴了计算机组成原理中的通信模型 —— 总线,所有需要和外部系统通信的系统,通过 ESB 进行标准化地转换从而消除协议、异构系统之间的差异,这样就可以利用现有的系统构建一个全新的松耦合的异构的分布式系统。微服务架构去掉 ESB,本质上是一种去中心化的思想。


「五脏六腑」


「心脏」

顺着上一节的思路,从最简单、最核心的问题出发,假设服务 A 要调用服务 B,会有什么问题?

  • 服务在哪?(服务治理问题)

  • 怎么调用?(服务调用问题)


这两个是最核心的问题,也是任何微服务框架首要解决的两个问题。

为了解决第一个问题 Spring Cloud 提供了 Eureka、Zookeeper、Cloud Foundry、Consul 等服务治理框架的集成。它们的工作模式是将所有的微服务注册到一个 Server 上,然后通过心跳进行服务健康监测。这样服务 A 调用 B 时可以从注册中心拿到可用的服务 B 的地址、端口进行调用。

第二个服务调用有人可能认为就是一个简单的 HTTP 或者 RPC 调用,不是什么问题。但是在分布式的场景下,服务调用需要考虑的因素会更多。比如一个服务有多个实例,此时请求进来了交给谁处理,请求的负载怎么平衡到各个实例,都是比较棘手的问题。Spring Cloud 提供了两种服务调用的方式:一种是 Ribbon + restTemplate,另一种是 Feign。

其中 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;
}

}

注册中心的地址为 http://localhost: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,当我们访问 http://localhost:8080/hello 时, HelloControler 接收到请求,并调用 HelloService 中的 helloService 方法, HelloService 中通过定义的 restTemplate 去调用 http://service-hello/hello 。此处要注意的是 @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







请到「今天看啥」查看全文