目錄
- spring cloud(一) 從一個(gè)簡(jiǎn)單的springboot服務(wù)開(kāi)始
- spring cloud(二) 起步袁稽,集成Eureka服務(wù)發(fā)現(xiàn)
- spring cloud(三)Eureka高可用性+Feign聲明式Rest客戶(hù)端
-
spring cloud(四) Eureka配置Httpbasic驗(yàn)證+Eureka配置詳解
未完待續(xù)
一勿璃、 為什么要使用微服務(wù)呢擒抛?它相比傳統(tǒng)的單體應(yīng)用有什么優(yōu)缺點(diǎn)呢?
從單體應(yīng)用和微服務(wù)的區(qū)別開(kāi)始說(shuō)起吧补疑。簡(jiǎn)單來(lái)說(shuō)歧沪,傳統(tǒng)的單體應(yīng)用就是把項(xiàng)目所需的全部文件打包在一起,而微服務(wù)指的是將功能拆分成可以獨(dú)立運(yùn)行的服務(wù)莲组,分開(kāi)部署诊胞,服務(wù)之間通過(guò)一些輕量級(jí)的通信機(jī)制進(jìn)行通信,這些服務(wù)一起構(gòu)建器整個(gè)系統(tǒng)锹杈。單從介紹來(lái)看微服務(wù)似乎有故意把簡(jiǎn)單的問(wèn)題復(fù)雜化的嫌疑撵孤,但是經(jīng)手過(guò)傳統(tǒng)的單體應(yīng)用的小伙伴肯定都深有體會(huì),隨著項(xiàng)目的不斷開(kāi)發(fā)竭望,項(xiàng)目的維護(hù)成本越來(lái)越高邪码,很多功能相互調(diào)用,牽一發(fā)而動(dòng)全身咬清。不僅如此闭专,編譯調(diào)試的過(guò)程也越來(lái)越慢。對(duì)于新的需求想用全新的技術(shù)棧提高開(kāi)發(fā)效率也是非常困難旧烧。那么微服務(wù)的出現(xiàn)正是為了解決日益復(fù)雜龐大的單體應(yīng)用所導(dǎo)致的項(xiàng)目維護(hù)難影钉,升級(jí)難的問(wèn)題。
那么列舉一下微服務(wù)的優(yōu)點(diǎn)吧:
- 易于開(kāi)發(fā)和維護(hù):因?yàn)橐粋€(gè)微服務(wù)通常只專(zhuān)注一個(gè)特定的業(yè)務(wù)功能掘剪,所以它的業(yè)務(wù)比較清晰平委,代碼量相對(duì)較少,開(kāi)發(fā)和維護(hù)單個(gè)微服務(wù)相對(duì)簡(jiǎn)單夺谁。
- 技術(shù)棧不受限:多個(gè)微服務(wù)之間通過(guò)輕量級(jí)的通信機(jī)制進(jìn)行通信廉赔,每個(gè)微服務(wù)完全可以選擇更適合此項(xiàng)業(yè)務(wù)的技術(shù)棧。
- 更合理利用資源:多個(gè)微服務(wù)分開(kāi)部署予权,可以針對(duì)io密集型的服務(wù)昂勉,和cpu密集型的服務(wù)部署在特定的服務(wù)器上∩ㄏ伲可針對(duì)某個(gè)特定的服務(wù)升級(jí)內(nèi)存或增加節(jié)點(diǎn)岗照。
- 復(fù)用性強(qiáng): 就像堆積木一樣,通用性強(qiáng)的服務(wù)可以用在多個(gè)項(xiàng)目中。
微服務(wù)的確定:
- 運(yùn)維困難: 更多的服務(wù)意味著需要投入更多的精力去維護(hù)項(xiàng)目攒至,與傳統(tǒng)的只需要保證一個(gè)服務(wù)正常運(yùn)行相比厚者,保證成噸的服務(wù)正常運(yùn)行顯然要更費(fèi)勁。
- 分布式固有的復(fù)雜性:在分布式系統(tǒng)中迫吐,網(wǎng)絡(luò)延遲库菲,分布式事務(wù),服務(wù)之間的容錯(cuò)等都是技術(shù)挑戰(zhàn)志膀。
- 接口的維護(hù)成本高: 微服務(wù)之間通過(guò)api進(jìn)行通信熙宇,如果修改某個(gè)服務(wù)的api將導(dǎo)致其他使用此api的服務(wù)做出相應(yīng)的調(diào)整。
- 重復(fù)的工作: 一些功能有可能多個(gè)服務(wù)都需要溉浙,此時(shí)可能會(huì)多個(gè)服務(wù)都實(shí)現(xiàn)同樣的功能烫止。
二、 微服務(wù)帶來(lái)了曙光戳稽,也帶來(lái)了挑戰(zhàn)馆蠕,那么應(yīng)對(duì)這些挑戰(zhàn)我們需要一些設(shè)計(jì)原則
- 單一職責(zé)原則
一個(gè)服務(wù)只干一件事了。 - 服務(wù)自治原則
每個(gè)服務(wù)得有基本的自理能力吧惊奇。開(kāi)發(fā)互躬、測(cè)試、部署颂郎、運(yùn)行都應(yīng)該可以獨(dú)立完成吼渡。 - 輕量級(jí)通信原則
一定要輕啊,帶寬很重要祖秒。也要滿(mǎn)足跨平臺(tái)的特性诞吱,常用的協(xié)議有:REST,AMQP,STOMP,MQTT - 微服務(wù)的粒度
如何確定服務(wù)的邊界這是嘗嘗爭(zhēng)論的焦點(diǎn)。需要考慮的因素很多,如業(yè)務(wù)本身,團(tuán)隊(duì)的情況等等毁兆。
三维苔、本系列實(shí)現(xiàn)微服務(wù)的技術(shù)選擇
- spring-cloud 可以很好的和springboot一起工作,屬于主流的解決方案,文檔豐富社區(qū)活躍。
- docker 出于方便,快捷以及易用性考慮選擇docker作為微服務(wù)的運(yùn)行平臺(tái)阿趁。
四、 先從springboot開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)單的服務(wù)間調(diào)用吧
場(chǎng)景介紹: 我們實(shí)現(xiàn)兩個(gè)服務(wù)坛猪,一個(gè)生產(chǎn)者服務(wù)脖阵,一個(gè)消費(fèi)者服務(wù)。消費(fèi)者調(diào)用生產(chǎn)者并獲取一個(gè)用戶(hù)信息墅茉。
技術(shù)選擇:java版本:1.8,springboot版本:2.0.5.RELEASE命黔,ORM:JPA,數(shù)據(jù)庫(kù):h2呜呐,依賴(lài)管理工具:maven,開(kāi)發(fā)工具:idea
1. 新建一個(gè)項(xiàng)目product_server
2. 添加pom依賴(lài)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yshmsoft</groupId>
<artifactId>product_server</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3. 在classpath下建立schema.sql建表語(yǔ)句和data.sql數(shù)據(jù)語(yǔ)句悍募,并添加如下內(nèi)容:
// schema.sql
drop table user if exists;
create table user(
id bigint generated by default as identity,
name varchar(20),
age int(3),
money decimal(10,2),
primary key(id)
);
//data.sql
insert into user(id,name,age,money) values (1, 'user1', 18, 233.22);
insert into user(id,name,age,money) values (2, 'user2', 22, 21133.22);
insert into user(id,name,age,money) values (3, 'user3', 34, 23333.22);
insert into user(id,name,age,money) values (4, 'user4', 54, 555233.22);
insert into user(id,name,age,money) values (5, 'user5', 19, 2332313.22);
insert into user(id,name,age,money) values (6, 'user6', 33, 2335522.22);
4. 新建User實(shí)體
package com.yshmsoft.entity;
import javax.persistence.*;
import java.math.BigDecimal;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private String name;
@Column
private Integer age;
@Column
private BigDecimal money;
//getter setter
}
5. 新建UserDao
package com.yshmsoft.dao;
import com.yshmsoft.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserDao extends JpaRepository<User,Long> {
}
6.新建UserController
package com.yshmsoft.controller;
import com.yshmsoft.dao.UserDao;
import com.yshmsoft.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
UserDao userDao;
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userDao.findById(id);
}
}
7.編寫(xiě)application.yml
server:
port: 8080
spring:
datasource:
platform: h2
schema: classpath:schema.sql
data: classpath:data.sql
jpa:
generate-ddl: false
show-sql: true
hibernate:
ddl-auto: none
logging:
level:
root: info
org.hibernate: info
8.添加啟動(dòng)類(lèi)
package com.yshmsoft;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ProductApplocation {
public static void main(String[] args) {
SpringApplication.run(ProductApplocation.class, args);
}
}
9. 運(yùn)行項(xiàng)目并訪(fǎng)問(wèn)http://localhost:8080/1
10. 新建一個(gè)comsume_server模塊
11. 同上一個(gè)項(xiàng)目一樣配置pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yshmsoft</groupId>
<artifactId>consome_server</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
12. 新建User類(lèi)
package com.yshmsoft.entity;
import java.math.BigDecimal;
public class User {
private Long id;
private String name;
private Integer age;
private BigDecimal money;
// getter setter
}
13.創(chuàng)建消費(fèi)者Controller
package com.yshmsoft.controller;
import com.yshmsoft.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class UserController {
@Autowired
RestTemplate restTemplate; //spring 提供的RestTemplate,方便調(diào)用Rest接口
@GetMapping("/user/{id}")
User getUserById(@PathVariable Long id) {
User user = restTemplate.getForObject("http://localhost:8080/" + id, User.class);
return user;
}
}
14. 創(chuàng)建配置文件application.yml
server:
port: 8000
logging:
level:
root: info
15. 創(chuàng)建啟動(dòng)類(lèi)
package com.yshmsoft;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class ConsumeApplication {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ConsumeApplication.class, args);
}
}
16 啟動(dòng)項(xiàng)目并訪(fǎng)問(wèn)http://localhost:8000/user/1
到此完成第一個(gè)示例的編寫(xiě)蘑辑。
五、 談一談上面的示例
完成了一個(gè)簡(jiǎn)單的微服務(wù)之間調(diào)用坠宴,上面這種微服務(wù)的實(shí)現(xiàn)方式會(huì)面臨什么問(wèn)題呢洋魂?
- 上面的例子中生產(chǎn)者的api是寫(xiě)死的,當(dāng)生產(chǎn)者的api地址改變時(shí)消費(fèi)者要跟著改變喜鼓。
- 這種方式服務(wù)的伸縮性比較差副砍,服務(wù)對(duì)單個(gè)服務(wù)的依賴(lài)性較強(qiáng)
- 每次新建一個(gè)服務(wù)都要配置api地址心累。
接下來(lái)我們開(kāi)始spring cloud的學(xué)習(xí)吧颠通,看看spring cloud為我們提供的解決方案址晕。敬請(qǐng)期待膀懈。