新聞中心
上一節(jié)( 跟我學(xué)Spring Cloud(Finchley版)-01-開篇 )說過,Spring Cloud是一個快速構(gòu)建分布式應(yīng)用的工具集。本節(jié),我們就來編寫一個簡單的分布式應(yīng)用,并探討這個分布式應(yīng)用有哪些問題。
成都創(chuàng)新互聯(lián)云計(jì)算的互聯(lián)網(wǎng)服務(wù)提供商,擁有超過13年的服務(wù)器租用、成都二樞機(jī)房、云服務(wù)器、網(wǎng)頁空間、網(wǎng)站系統(tǒng)開發(fā)經(jīng)驗(yàn),已先后獲得國家工業(yè)和信息化部頒發(fā)的互聯(lián)網(wǎng)數(shù)據(jù)中心業(yè)務(wù)許可證。專業(yè)提供云主機(jī)、網(wǎng)頁空間、域名申請、VPS主機(jī)、云服務(wù)器、香港云服務(wù)器、免備案服務(wù)器等。
服務(wù)消費(fèi)者 & 提供者
本書使用服務(wù)提供者與服務(wù)消費(fèi)者來描述微服務(wù)之間的調(diào)用關(guān)系。下表解釋了服務(wù)提供者與服務(wù)消費(fèi)者。
表-服務(wù)提供者與服務(wù)消費(fèi)者
名詞 | 定義 |
---|---|
服務(wù)提供者 | 服務(wù)的被調(diào)用方(即:為其他服務(wù)提供服務(wù)的服務(wù)) |
服務(wù)消費(fèi)者 | 服務(wù)的調(diào)用方(即:依賴其他服務(wù)的服務(wù)) |
以電影售票系統(tǒng)為例。如圖,用戶向電影微服務(wù)發(fā)起了一個購票的請求。在進(jìn)行購票的業(yè)務(wù)操作前,電影微服務(wù)需要調(diào)用用戶微服務(wù)的接口,查詢當(dāng)前用戶的余額是多少、是不是符合購票標(biāo)準(zhǔn)等。在這種場景下,用戶微服務(wù)就是一個服務(wù)提供者,電影微服務(wù)則是一個服務(wù)消費(fèi)者。
圍繞該場景,先來編寫一個用戶微服務(wù),然后編寫一個電影微服務(wù)。
TIPS
服務(wù)消費(fèi)者和服務(wù)提供者描述的只是微服務(wù)之間的調(diào)用關(guān)系,一般成對出現(xiàn)。例如本文,用戶微服務(wù)是是電影微服務(wù)的服務(wù)提供者,電影微服務(wù)是用戶微服務(wù)的服務(wù)消費(fèi)者。很多初學(xué)者和筆者交流時(shí),會描述提供者如何如何……仿佛消費(fèi)者和提供者是微服務(wù)的固有屬性,這是不對的——例如A調(diào)用B,B調(diào)用C,那么B相對A就是提供者,B相對C就消費(fèi)者。
Spring Boot/Spring Cloud應(yīng)用開發(fā)套路
Spring Boot/Spring Cloud時(shí)代后,應(yīng)用開發(fā)基本遵循三板斧:
- 加依賴
- 加注解
- 寫配置
至于你的業(yè)務(wù)代碼,該怎么寫還怎么寫。
TIPS
對于懶人,可使用Spring Initilizr(IDEA、Spring Tool Suite等IDE上均有集成,也可在http://start.spring.io 使用網(wǎng)頁版)創(chuàng)建應(yīng)用,它會給你生成項(xiàng)目的依賴以及項(xiàng)目的骨架。后續(xù),筆者會以番外的形式更新相關(guān)教程。
編寫服務(wù)提供者【用戶微服務(wù)】
創(chuàng)建一個Maven項(xiàng)目,依賴如下:
4.0.0 com.itmuch.cloud microservice-simple-provider-user 0.0.1-SNAPSHOT jar org.springframework.boot spring-boot-starter-parent 2.0.7.RELEASE UTF-8 1.8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-jpa com.h3database h3 org.projectlombok lombok true org.springframework.cloud spring-cloud-dependencies Finchley.SR2 pom import org.springframework.boot spring-boot-maven-plugin 其中,
spring-boot-starter-web
提供了Spring MVC的支持;spring-boot-starter-data-jpa
提供了Spring Data JPA的支持;h3
是一種內(nèi)嵌的數(shù)據(jù)庫,語法和MySQL類似(筆者實(shí)在沒有動力為了簡單的演示再寫一大堆內(nèi)容去演示怎么安裝MySQL數(shù)據(jù)庫);lombok
則是一款開發(fā)利器,可以幫助你簡化掉N多冗余代碼。WARNING
- Lombok之前,必須為你的IDE安裝Lombok插件!可參考:
TIPS
- Lombok快速上手:
- Lombok官方網(wǎng)站:
- Lombok之前,必須為你的IDE安裝Lombok插件!可參考:
創(chuàng)建實(shí)體類:
@Entity @Data @NoArgsConstructor @AllArgsConstructor public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Column private String username; @Column private String name; @Column private Integer age; @Column private BigDecimal balance; }
創(chuàng)建DAO:
@Repository public interface UserRepository extends JpaRepository
{ } 創(chuàng)建Controller:
@RequestMapping("/users") @RestController public class UserController { @Autowired private UserRepository userRepository; @GetMapping("/{id}") public Optional
findById(@PathVariable Long id) { return this.userRepository.findById(id); } } 其中,
@GetMapping
,是Spring 4.3提供的新注解。它是一個組合注解,等價(jià)于@RequestMapping(method = RequestMethod.GET)
,用于簡化開發(fā)。同理還有@PostMapping
、@PutMapping
、@DeleteMapping
、@PatchMapping
等。編寫啟動類:
@SpringBootApplication public class ProviderUserApplication { public static void main(String[] args) { SpringApplication.run(ProviderUserApplication.class, args); } /** * 初始化用戶信息 * 注:Spring Boot2不能像1.x一樣,用spring.datasource.schema/data指定初始化SQL腳本,否則與actuator不能共存 * 原因詳見: * https://github.com/spring-projects/spring-boot/issues/13042 * https://github.com/spring-projects/spring-boot/issues/13539 * * @param repository repo * @return runner */ @Bean ApplicationRunner init(UserRepository repository) { return args -> { User user1 = new User(1L, "account1", "張三", 20, new BigDecimal(100.00)); User user2 = new User(2L, "account2", "李四", 28, new BigDecimal(180.00)); User user3 = new User(3L, "account3", "王五", 32, new BigDecimal(280.00)); Stream.of(user1, user2, user3) .forEach(repository::save); }; } }
@SpringBootApplication
是一個組合注解,它整合了@Configuration
、@EnableAutoConfiguration
和@ComponentScan
注解,并開啟了Spring Boot程序的組件掃描和自動配置功能。在開發(fā)Spring Boot程序的過程中,常常會組合使用@Configuration
、@EnableAutoConfiguration
和@ComponentScan
等注解,所以Spring Boot提供了@SpringBootApplication
,來簡化開發(fā)。在啟動時(shí),我們使用了
ApplicationRunner init(UserRepository repository)
初始化了三條數(shù)據(jù),分別是張三、李四、王五。@Bean
則是一個方法注解,作用是實(shí)例化一個Bean并使用該方法的名稱命名。類似于XML配置方式的<bean id="init" class="...ApplicationRunner"/>
。編寫配置文件
application.yml
:server: # 指定Tomcat端口 port: 8000 spring: jpa: # 讓hibernate打印執(zhí)行的SQL show-sql: true logging: level: root: INFO # 配置日志級別,讓hibernate打印出執(zhí)行的SQL參數(shù) org.hibernate: INFO org.hibernate.type.descriptor.sql.BasicBinder: TRACE org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
傳統(tǒng)Web應(yīng)用開發(fā)中,常使用properties格式文件作為配置文件。Spring Boot以及Spring Cloud支持使用properties或者yml格式的文件作為配置文件。
yml文件格式是YAML(Yet Another Markup Language)編寫的文件格式,YAML和properties格式的文件可互相轉(zhuǎn)換,例如本節(jié)中的application.yml,就等價(jià)于如下的properties文件:
server.port=8000 spring.jpa.show-sql=true logging.level.root=INFO logging.level.org.hibernate=INFO logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE logging.level.org.hibernate.type.descriptor.sql.BasicExtractor=TRACE
從中不難看出,YAML比properties結(jié)構(gòu)清晰;可讀性、可維護(hù)性也更強(qiáng),并且語法非常簡潔。因此,本書使用YAML格式作為配置文件。但,yml有嚴(yán)格的縮進(jìn),并且key與value之間使用: 分隔,冒號后的空格不能少,請大家注意。
測試
訪問http://localhost:8000/users/1
,可獲得結(jié)果:
{"id":1,"username":"account1","name":"張三","age":20,"balance":100.00}
編寫服務(wù)消費(fèi)者【電影微服務(wù)】
我們已經(jīng)編寫了一個服務(wù)提供者(用戶微服務(wù)),本節(jié)來編寫一個服務(wù)消費(fèi)者(電影微服務(wù))。該服務(wù)非常簡單,它使用RestTemplate調(diào)用用戶微服務(wù)的API,從而查詢指定id的用戶信息。
創(chuàng)建一個Maven項(xiàng)目,ArtifactId是
microservice-simple-consumer-movie
。加依賴:
org.springframework.boot spring-boot-starter-web 創(chuàng)建實(shí)體類:
@Data @AllArgsConstructor @NoArgsConstructor public class User { private Long id; private String username; private String name; private Integer age; private BigDecimal balance; }
創(chuàng)建啟動類:
@SpringBootApplication public class ConsumerMovieApplication { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(ConsumerMovieApplication.class, args); } }
創(chuàng)建Controller:
@RequestMapping("/movies") @RestController public class MovieController { @Autowired private RestTemplate restTemplate; @GetMapping("/users/{id}") public User findById(@PathVariable Long id) { // 這里用到了RestTemplate的占位符能力 User user = this.restTemplate.getForObject("http://localhost:8000/users/{id}", User.class, id); // ...電影微服務(wù)的業(yè)務(wù)... return user; } }
由代碼可知,Controller使用RestTemplate調(diào)用用戶微服務(wù)的RESTful API。
編寫配置文件
application.yml
:server: port: 8010
拓展閱讀
本文使用RestTemplate實(shí)現(xiàn)了基于HTTP的遠(yuǎn)程調(diào)用,事實(shí)上,Spring 5開始,WebFlux提供了Reactive的Web Client:WebClinet
,使用方式和RestTemplate基本類似,但性能更強(qiáng),吞吐更好。有興趣的可前往
測試
訪問:http://localhost:8010/movies/users/1
,結(jié)果如下:
{"id":1,"username":"account1","name":"張三","age":20,"balance":100.00}
存在的問題
至此,我們已經(jīng)實(shí)現(xiàn)了這個最簡單的分布式應(yīng)用,應(yīng)用之間通過HTTP通信。代碼非常簡單,但這些簡單的代碼里,存在著若干問題:
應(yīng)用沒有監(jiān)控,沒有畫板,一切指標(biāo)都沒有。在這個Growth Hack逐漸成為主流的時(shí)代,不弄個Dashboard把系統(tǒng)壓力、QPS、CPU、內(nèi)存、日活啥的可視化,你好意思出來混嗎……
地址硬編碼問題——電影微服務(wù)中將用戶微服務(wù)的地址寫死,如果用戶微服務(wù)地址發(fā)生變化,難道要重新上線電影微服務(wù)嗎?
你可能會質(zhì)疑:用戶微服務(wù)地址為什么會變,讓它保持不變就行了啊,這不是問題。這里舉兩個例子:
例1:如果你用Docker,那么地址幾乎每次啟動都會變……
例2:你之前用的是TXYun,后來你想把用戶微服務(wù)遷移到Aliyun。這個時(shí)候IP就會發(fā)生變化。我相信你不會樂意找到哪些服務(wù)調(diào)用了用戶微服務(wù)的接口,然后所有調(diào)用用戶微服務(wù)的服務(wù)統(tǒng)一修改地址……
負(fù)載均衡如何考慮?難道得在電影微服務(wù)和用戶微服務(wù)之間加個NGINX做負(fù)載均衡嗎?聽起來是可行的,但如果有10000+服務(wù)(這并不夸張,我司的微服務(wù)數(shù)目是這個數(shù)字乘以N,N >= m,哈哈哈)那這個NGINX的配置得有多復(fù)雜……
服務(wù)之間沒有容錯機(jī)制,相信對技術(shù)有激情的你已經(jīng)不止一次聽過容錯、降級、fallback、回退之類的詞匯。
如果應(yīng)用發(fā)生故障,你怎么迅速找到問題所在?
- 用戶認(rèn)證和授權(quán)呢?被狗吃了嗎?
如上詞匯,你可能看得懂,你也可能看不懂。沒有關(guān)系,請繼續(xù)閱讀,筆者將會用通俗的語言去描述,在你看完本系列后,你會知道,原來那些所謂的高大上的理論、術(shù)語、技術(shù),原來也就是這么回事兒。
配套代碼
- GitHub:
- https://github.com/eacdy/spring-cloud-study/tree/master/2018-Finchley/microservice-simple-provider-user
- https://github.com/eacdy/spring-cloud-study/tree/master/2018-Finchley/microservice-simple-consumer-movie
- Gitee:
- https://gitee.com/itmuch/spring-cloud-study/tree/master/2018-Finchley/microservice-simple-provider-user
- https://gitee.com/itmuch/spring-cloud-study/tree/master/2018-Finchley/microservice-simple-consumer-movie
原文:http://www.itmuch.com/spring-cloud/finchley-2/ 轉(zhuǎn)載請說明出處。
干貨分享
分享題目:跟我學(xué)SpringCloud(Finchley版)-02-構(gòu)建分布式應(yīng)用
地址分享:http://www.ef60e0e.cn/article/geidhi.html