[译]Spring构建微服务
此文为译文,原文地址
介绍
本文通过一个使用Spring、Spring Boot和Spring Cloud的小例子来说明如何构建微服务系统。
我们可以通过数个微服务组合成一个大型系统。
我们可以想象下有这么一个网上商城,它由用户、目录、购物车、订单等多个独立的为服务组成。
这里难免需要安装和配置不少组件才能构建这样一个系统。为了让它们更好的合作,你需要熟悉Spring Boot、Spring Cloud。
本文的目标很明确,就是一步一步构建一个最简单的系统。因此,这里只会实现系统中的一小部分-用户微服务。
Web应用可以通过请求restful api访问用户微服务。这里也会包含发现服务-让其他服务可以知道彼此。
其他资源
本文只是讨论了一个最简单的系统,更多的内容,你可以阅读Josh Long的博客
服务注册
当你有多个服务协同工作时,它们需要互相彼此知道。如果你之前了解java RMI机制,你可能还记得,它依赖于一个注册中心,从而使RMI服务能够找到对方。微服务也有同样的需求。
Netflix的开发人员设计并开源了一套服务注册系统,叫做Eureka。目前这套系统已被合并进了Spring Cloud,我们可以很容易的运行一个Eureka服务。例如:
@SpringBootApplication
@EnableEurekaServer
public class ServiceRegistrationServer {
public static void main(String[] args) {
// 配置文件 registration-server.yml
System.setProperty("spring.config.name", "registration-server");
SpringApplication.run(ServiceRegistrationServer.class, args);
}
}
就是这么简单。
POM中的核心内容如下:
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>Angel.SR3</version> <!-- Name of release train -->
</parent>
<dependencies>
<dependency>
<!-- Setup Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<!-- Setup Spring MVC & REST, use Embedded Tomcat -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<!-- Spring Cloud starter -->
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<!-- Eureka for service registration -->
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
Spring Boot的默认配置可以查看application.properties
或者application.yml
文件。当你有多个Spring Boot应用的时候,你可以配置spring.config.name
属性来让Spring Boot查找不同的配置文件。
此应用还需配置registration-server.properties
或registration-server.yml
文件。以下是registration-server.yml
中的相关配置:
# Configure this Discovery Server
eureka:
instance:
hostname: localhost
client: # 只注册服务端
registerWithEureka: false
fetchRegistry: false
server:
port: 1111 # HTTP (Tomcat) port
Eureka默认运行在8761端口,这里我们把它修改为1111端口。配置中制定了这里是服务端,并且阻止注册自身服务。
现在运行我们的注册服务,你可以通过 http://localhost:1111来访问Eureka的主界面。
创建微服务:用户服务
微服务是一个用来处理一个明确需求的独立组件。
我们总是在强调要构建高内聚,低耦合的架构,这已经是老生常谈了。但是,这里我们不是在组件(Spring Beans)级别实现,而是在接口之间实现。
例如,我有一个账户管理的微服务需要使用Spring Data AccountRepository
来实现一个JPA,还需要使用Spring REST来提供RESTful接口显示账户信息。这正好就是实现了一个简单的spring boot应用。
我们如何让它被注册到注册服务中:
@EnableAutoConfiguration
@EnableDiscoveryClient
@Import(AccountsWebApplication.class)
public class AccountsServer {
@Autowired
AccountRepository accountRepository;
public static void main(String[] args) {
// 配置文件 accounts-server.yml
System.setProperty("spring.config.name", "accounts-server");
SpringApplication.run(AccountsServer.class, args);
}
}
答案是注解:
@EnableAutoConfiguration
- 定义了这是一个Spring Boot应用@EnableDiscoveryClient
- 运行服务被注册到注册服务中@Import(AccountsWebApplication.class)
引入配置类
此外,YML配置文件内容如下:
# Spring properties
spring:
application:
name: accounts-service
# Discovery Server Access
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1111/eureka/
# HTTP Server
server:
port: 2222 # HTTP (Tomcat) port
说明:
1.设置应用名为accounts-service
,注册和访问都使用这个名字
2.服务发布在2222端口
3.配置Eureka 服务URL
现在运行服务然后刷新http://localhost:1111 ,你会看到ACCOUNTS-SERVICE显示在应用列表中。
有时候,注册服务需要用10到20秒时间。你可以访问http://localhost:1111/eureka/apps/来查询更多的信息:
<applications>
<versions__delta>1</versions__delta>
<apps__hashcode>UP_1_</apps__hashcode>
<application>
<name>ACCOUNTS-SERVICE</name>
<instance>
<hostName>autgchapmp1m1.corp.emc.com</hostName>
<app>ACCOUNTS-SERVICE</app>
<ipAddr>172.16.84.1</ipAddr><status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">3344</port>
<securePort enabled="false">443</securePort>
...
</instance>
</application>
</applications>
访问微服务
Spring提供了RestTemplate
类来访问RESTful类。它可以让你发送HTTP请求至RESTful服务并且接收和处理不同类型的响应数据-包括JSON和XML。
封装微服务调用
在客户端应用里有一个WebAccountService
类:
@Service
public class WebAccountsService {
@Autowired // Spring Cloud 自动注入
@LoadBalanced
protected RestTemplate restTemplate;
protected String serviceUrl;
public WebAccountsService(String serviceUrl) {
this.serviceUrl = serviceUrl.startsWith("http") ?
serviceUrl : "http://" + serviceUrl;
}
public Account getByNumber(String accountNumber) {
Account account = restTemplate.getForObject(serviceUrl
+ "/accounts/{number}", Account.class, accountNumber);
if (account == null)
throw new AccountNotFoundException(accountNumber);
else
return account;
}
...
}
WebAccountService
使用RestTemplate从微服务中获取数据
访问微服务
在WebAccountController
设置serviceUrl
:
@SpringBootApplication
@EnableDiscoveryClient
@ComponentScan(useDefaultFilters=false)
public class WebServer {
public static void main(String[] args) {
// Will configure using web-server.yml
System.setProperty("spring.config.name", "web-server");
SpringApplication.run(WebServer.class, args);
}
@Bean
public WebAccountsController accountsController() {
// 1. 不应该写死 ,这里只是示例
// 2. 大小写不敏感,也可以是http://accounts-service
return new WebAccountsController
("http://ACCOUNTS-SERVICE"); // serviceUrl
}
}
以下几点需要注意:
WebController
是一个典型的Spring MVC控制器,此应用使用thymeleaf作为视图引擎。Spring Boot会默认扫描注解了
@Component
的类,在本例中,我们自己创建了WebAccountController
,所以我取消了自动扫描@ComponentScan(useDefaultFilters=false)
。service-url 需要与
spring.application.name
中一致,而不是真实的访问地址。如account-service.yml中的accounts-service。
RestTemplate 负载均衡
Spring Cloud会自动配置RestTemplate使用Netflix的 Ribbon来实现HTTP客户端。
当你的某个服务存在多个实例是,Ribbon会使用自动选择其中的一个。
如果你查看RibbonClientHttpRequestFactory的源码,你会发现:
String serviceId = originalUri.getHost();
ServiceInstance instance =
loadBalancer.choose(serviceId); // 负载均衡
... if instance non-null (service exists) ...
URI uri = loadBalancer.reconstructURI(instance, originalUri);
RestTemplate实例是线程安全的,它可以访问任意数量的应用程序中的不同服务。
配置
现在我们配置web-server.yml:
# Spring Properties
spring:
application:
name: web-service
# Discovery Server Access
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1111/eureka/
# HTTP Server
server:
port: 3333 # HTTP (Tomcat) port
AccountsWebApplication 配置
@SpringBootApplication
@EntityScan("io.pivotal.microservices.accounts")
@EnableJpaRepositories("io.pivotal.microservices.accounts")
@PropertySource("classpath:db-config.properties")
public class AccountsWebApplication {
...
}
这是账户服务的配置类,其中注解的含义如下:
@SpringBootApplication - 定义了这是一个Sping Boot应用。这个注解等同于@EnableAutoConfiguration
, @Configuration和 @ComponentScan(默认情况Spring会扫描当前包和子包中的所有可能的beans,如AccountController
和AccountRepository)@EntityScan("io.pivotal.microservices.accounts") - 这里用了JPA,所有我需要用到@Entity类。
@EnableJpaRepositories("io.pivotal.microservices.accounts") - 搜索Repository接口并使用JPA自动实现。(Spring Data JPA)
@PropertySource("classpath:db-config.properties")- 配置数据源属性
至此,我们已经实现了一个简单的微服务示例,如果什么地方没说明白的的,请下载并阅读源代码~~
各位看官,请打赏。
[译]Spring构建微服务的更多相关文章
- 构建微服务:Spring boot
构建微服务:Spring boot 在上篇文章构建微服务:Spring boot 提高篇中简单介绍了一下spring data jpa的基础性使用,这篇文章将更加全面的介绍spring data jp ...
- 基于Spring Cloud和Netflix OSS构建微服务,Part 2
在上一篇文章中,我们已使用Spring Cloud和Netflix OSS中的核心组件,如Eureka.Ribbon和Zuul,部分实现了操作模型(operations model),允许单独部署的微 ...
- Spring Cloud构建微服务架构(二)服务消费者
Netflix Ribbon is an Inter Process Communication (IPC) cloud library. Ribbon primarily provides clie ...
- 构建微服务:Spring boot 入门篇
什么是Spring Boot Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而 ...
- Spring Cloud构建微服务架构:服务网关(路由配置)【Dalston版】
转载:http://blog.didispace.com/spring-cloud-starter-dalston-6-2/ 原创 2017-08-26 翟永超 Spring Cloud 被围观 ...
- Cola Cloud 基于 Spring Boot, Spring Cloud 构建微服务架构企业级开发平台
Cola Cloud 基于 Spring Boot, Spring Cloud 构建微服务架构企业级开发平台: https://gitee.com/leecho/cola-cloud
- Spring Cloud构建微服务架构(五)服务网关
通过之前几篇Spring Cloud中几个核心组件的介绍,我们已经可以构建一个简略的(不够完善)微服务架构了.比如下图所示: 我们使用Spring Cloud Netflix中的Eureka实现了服务 ...
- Spring Cloud构建微服务架构 - 服务网关
通过之前几篇Spring Cloud中几个核心组件的介绍,我们已经可以构建一个简略的(不够完善)微服务架构了.比如下图所示: alt 我们使用Spring Cloud Netflix中的Eureka实 ...
- 手把手教你用Spring Cloud和Docker构建微服务
什么是Spring Cloud? Spring Cloud 是Pivotal提供的用于简化分布式系统构建的工具集.Spring Cloud引入了云平台连接器(Cloud Connector)和服务连接 ...
随机推荐
- 码农干货系列【20】--add gtTime to Promise.js
使用场景 在一些时候,希望一件task不能太快完成,需要大于多少时间才可以执行,就可以使用Promise的gtTime方法. 使用方式 Promise.gtTime(f1(), 5000).then( ...
- iOS笔记之NSSet
一.简介 NSSet到底什么类型,其实它和NSArray功能性质一样,用于存储对象,属于集合: NSSet , NSMutableSet类声明编程接口对象,无序的集合,在内存中存储方式是不连续的, ...
- cocos2dx骨骼动画Armature源码分析(三)
代码目录结构 cocos2dx里骨骼动画代码在cocos -> editor-support -> cocostudio文件夹中,win下通过筛选器,文件结构如下.(mac下没有分,是整个 ...
- iOS之深拷贝与浅拷贝
在最开始,我们需要清楚一些关于内存分配方式的基础知识. 一般来说分为栈.堆.静态变量存储区.全局变量存储区.代码区. 前两个大家都懂的.通常将后三个合并称之为静态存储区,存储的是一些全局变量.静态变量 ...
- TortoiseSVN和VisualSVN-Server的配置使用,外网访问SVN版本库
TortoiseSVN和VisualSVN-Server的配置使用,外网访问SVN版本库 SVN客户端程序:TortoiseSVN SVN服务器程序:VisualSVN-Server ######## ...
- Oracle索引梳理系列(六)- Oracle索引种类之函数索引
版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...
- MongoDB学习笔记~环境搭建
回到目录 Redis学习笔记已经告一段落,Redis仓储也已经实现了,对于key/value结构的redis我更愿意使用它来实现数据集的缓存机制,而对于结构灵活,查询效率高的时候使用redis就有点不 ...
- 搞ACM的你伤不起[转自RoBa]------(看一次,笑一次)
RoBa原创,转载请注明出处 劳资六年前开始搞ACM啊!!!!!!!!!! 从此踏上了尼玛不归路啊!!!!!!!!!!!! 谁特么跟劳资讲算法是程序设计的核心啊!!!!!! 尼玛除了面试题就没见过用 ...
- 追MM的各种算法
原文:http://blog.sae.sina.com.cn/archives/3542#more-3542 看到一篇文章把算法描述的相当的好,先收藏了! 动态规划 基本上就是说:你追一个MM的时候, ...
- Si2155
http://www.edom.com.tw/cn/index.jsp?m=prodview&id=1702 Description:新型的Si2155 电视调谐器IC扩展了Silicon L ...