如何将 Spring Cloud Netflix 框架集成到现有 API 中
sad10a
8年前
<p>当前, RESTful API 可能已经在你所在的组织中达到了某种 程度的 成功。当越来越多的微服务或API涌现出来时,API间的依赖也随之增长,对服务的要求也更多的落在了提供尽可能稳定的API或微服务。通常,这个过程以多实例 运行 及某种形式的负载均衡展开,以满足需求。</p> <p>Netflix (OSS) Spring Cloud项目</p> <p>随着 Netflix's (OSS) Spring Cloud 项目的流行和成功,或许可以考虑将它集成到那些以任务为关键的API里。 Netflix的项目建立在 Spring Boot 框架之上,提供了如下组件:</p> <ul> <li> <p>Eureka用于Spring管理下的bean服务发现</p> </li> <li> <p>Zuul处理路由服务,被视为请求的”守门员“</p> </li> <li> <p>Ribbon用于动态路由和负载均衡</p> </li> <li> <p>Hystrix提供了 断路器功能,以处理无响应的API调用</p> </li> <li> <p>Turbine提供了 关于 Hystrix的全部可用断路器的 信息</p> </li> </ul> <p>同时推荐使用 Spring Cloud Config ,它把应用配置集中到了一个Git仓库。</p> <h2><strong>第一步:使用Spring Boot</strong></h2> <p>如果你的API或微服务是在Spring Boot的基础上构建的,那么你的当前准备已就绪,可以直接进入下节。然而,你的服务很可能并没有在Spring Boot上 运行 ,如果是这样,你需要采取一些措施,才能使用Netflix提供给社区的OSS工具。</p> <p>对于初学者,请参考当前Spring Boot文档中的 将已有项目转换到Spring Boot 章节。文中对转换的过程提供了一些注意事项和建议(文章还指出,将非web应用,如API服务,转换到Spring Boot会更容易一些)。此时需要将创建ApplicationContext的代码替换为调用SpringApplication的代码。Application类需要继承SpringBootServletInitializer,然后启用Spring Boot自动配置:</p> <pre> @Configuration @EnableAutoConfiguration @ComponentScan public class Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure( SpringApplicationBuilder application) { return application; } }</pre> <p>可以添加如下的main方法,以启动应用:</p> <pre> public static void main(String[] args) { SpringApplication.run(Application.class, args); }</pre> <p>对于已有的Servlet应用,如果用的是3.0以上的版本,转换工作会简单很多,尤其是用了Spring Servlet初始化工具支持类的。</p> <p>对于更复杂的应用,需要先进行分析,以决定最佳实践是否是重新开始一个Spring Boot应用,然后将原有类和方法迁移到这个新应用中。</p> <p>当你可以启动Spring Boot应用,并且也验证过API之后,就可以引入Netflix的组件了。</p> <h2><strong>创建Eureka和Zuul服务器</strong></h2> <p>要添加的第一个服务器是Eureka服务器,它将用于处理服务发现。 Eureka服务器是一个标准的Spring Boot应用程序,使用简单的main()方法:</p> <pre> @SpringBootApplication @EnableEurekaServer @EnableDiscoveryClient public class EurekaApplication { public static void main(String[] args) { SpringApplication.run( EurekaApplication.class, args); } }</pre> <p>Zuul服务器将充当网守,或者最终为您的微服务连接主服务器。这里,使用以下main()方法创建另一个标准的Spring Boot应用程序实例:</p> <pre> @SpringBootApplication @Controller @EnableZuulProxy public class ZuulApplication { public static void main(String[] args) { new SpringApplicationBuilder( ZuulApplication.class) .web(true).run(args); } }</pre> <p>此时,Zuul服务器已启动,正在运行,并准备好处理使用Eureka注册的请求。 默认情况下,功能区服务也将运行,作为负载平衡器,客户端通过Zuul访问该服务。</p> <h2><strong>更新微服务/API</strong></h2> <p>为了用Eureka注册服务, 需要把@EnableDiscoveryClient注解加到应用程序的类中, 如下面的例子:</p> <pre> @SpringBootApplication @EnableDiscoveryClient public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }</pre> <p>当服务启动时, 会开启Eureka注册, 这样就可以通过Zuul网关服务器访问Eureka。这时候,你可以引进服务的多个实例。这些实例会通过Zuul服务器中的Ribbon进行自动注册和加载.</p> <h2><strong>添加 Hystrix 和 Turbine 到 Mix 中</strong></h2> <p>这时,客户端可以通过Zuul服务来访问你的服务。从监查的角度来看, 添加Hystrix和引入Eureka 及Zuul服务器一样容易——只需启动基础Spring Boot应用,然后使用@EnableHystrixDashboard注解。</p> <pre> @SpringBootApplication @Controller @EnableHystrixDashboard public class HystrixDashboardApplication extends SpringBootServletInitializer { public static void main(String[] args) { new SpringgApplicationBuilder( HystrixDashboardApplication.class) .web(true).run(args); } }</pre> <p>设置Turbine,添加@EnableTurbineAmqp注解到其他基础Spring Boot应用:</p> <pre> @SpringBootApplication @EnableTurbineAmqp @EnableDiscoveryClient public class TurbineApplication { public static void main(String[] args) { new SpringApplicationBuilder( TurbineApplication.class).run(args); } }</pre> <h2><strong>增加"断路器"功能</strong></h2> <p>Netflix Hystrix 为此服务的使用者提供了断路器功能。如果服务器停止响应,Hystrix 能够把 API 调用重定向到此服务的内部方法中去。这样,应用程序就能处理服务不响应的情况。</p> <p>Hystrix 拥有以下功能:它能在此后的每次调用都打开回路并且“快速失败”(忽略当前的服务调用只使用内部的方法),这种状况将持续,直到服务变得可用为止。</p> <p>Hystrix 产品提供了一个看板,能提供被监测的服务的动态列表。</p> <p>在上面的 Hystrix 看板图中,能看到 getMovie 这个 API 调用当前没有响应,导致回路一直处于打开状态,从而会一直调用已经配置好的回调方法。</p> <p>为了在程序中使用"断路器"功能,你需要在 Spring 启动程序中添加使用 @EnableCircuitBreaker 注释标签。从那里,可以使用 @HystrixCommand() 注释标签,示例如下:</p> <pre> @HystrixCommand(fallbackMethod = "baseResults") public ResponseEntity<List<Result>> getResults(Long id) { ... } public ResponseEntity<List<Result>> getBaseResults(Long id) { ... }</pre> <p>在上面的代码示例中,当服务调用 getResults() 方法遇到服务超时的错误时候,getBaseResults() 方法就会被调用直到回路被关闭—— 一旦失败的服务问题重新联机,就会发生这种情况 。</p> <h2><strong>挑战</strong></h2> <p>到了这一步,你的核心应用程序或API将作为一个拥有单个或多个实例的Spring Boot应用运行。 这些实例在Eureka服务中注册,并为Zuul网关的请求提供服务,其中也包括用于负载平衡的Ribbon 。当一项服务停止响应时,由于网络和服务的超时设定,Hystrix断路器会打开并提供可用的后降方法。Netflix的Spring Cloud项目功能也相当不错,但它也面临着一些挑战。</p> <p>最大的挑战是对开发者的影响,他们可能已经习惯于一种单一的应用程序服务实例运行。而现在,开发者不得不确保额外的两个服务(Eureka和Zuul)运行——这就增加了本地开发的工作复杂度。</p> <p>当然,依赖另一个通过Eureka传达的服务也会让工作变得复杂——这可能会使本地运行受限。在这种情况下,开发者或许会需要用另一个名字在Eureka上注册一个当地服务器实例—— 当它与集中式配置服务一起使用时可能存在挑战。</p> <h2><strong>展望未来</strong></h2> <p>本文的目的是回顾 Netfix Spring Cloud 项目包含的组件。因为 考虑到生产环境 ,此文故意省略了多个Zuul 和 Eureka 实例。此外,由于类似的原因,我没有深入Spring 配置的细节,RabbitMQ 的使用,Hystrix 和 Turbine 的功能。</p> <p>如果您的 API 或者微服务已经达到这一步,那么,由 Netflix 的 Spring Cloud 项目提供的特性和功能将使它成为不二之选,我强烈建议您为 解决方案多 花些时间,以 评估使用的开源软件。尽管将您的服务转换为 Spring Boot需要时间和精力,但是从长期收益来看,这短时间内的付出是值得的。</p> <p> </p> <p>来自:https://www.oschina.net/translate/integration-the-spring-cloud-netflix-framework-int</p> <p> </p>