|
微服務(wù)架構(gòu)設(shè)計(jì)模式對(duì)于單塊設(shè)計(jì)模式而言有很多優(yōu)點(diǎn)。核心思想就是將單個(gè)巨大的應(yīng)用劃分成互聯(lián)的不同應(yīng)用。與單塊應(yīng)用類似,每個(gè)微服務(wù)都有其自己的層級(jí)架構(gòu)。 使用下列的模式,微服務(wù)可以輕易取得如下優(yōu)點(diǎn): 可擴(kuò)展性一款典型的應(yīng)用會(huì)使用3個(gè)方向的擴(kuò)展。X軸擴(kuò)展是指橫向擴(kuò)展應(yīng)用,Y軸擴(kuò)展是指劃分不同的應(yīng)用功能,Z軸擴(kuò)展是指對(duì)于數(shù)據(jù)的分區(qū)(partioning)和分片(sharding)。當(dāng)Y軸擴(kuò)展應(yīng)用到單塊應(yīng)用時(shí),該應(yīng)用就會(huì)被打散,按照符合微服務(wù)特性的業(yè)務(wù)功能,形成許多更小的單元。 模式:每個(gè)微服務(wù)有其隔離的實(shí)例或容器。服務(wù)級(jí)別的負(fù)載均衡可以通過將相同服務(wù)托管于多個(gè)實(shí)例實(shí)現(xiàn)。 可用性如同相同的微服務(wù)會(huì)托管于多個(gè)實(shí)例中一樣,微服務(wù)會(huì)部署于不同的實(shí)例中,這使整個(gè)系統(tǒng)高度可用。 模式:服務(wù)級(jí)別的負(fù)載均衡可被用以實(shí)現(xiàn)高可用性,斷路器模式可被用以實(shí)現(xiàn)容錯(cuò),服務(wù)配置和服務(wù)發(fā)現(xiàn)可使發(fā)現(xiàn)新服務(wù)以通訊成為可能。 持續(xù)部署每個(gè)微服務(wù)均是獨(dú)立的。這就導(dǎo)致任何服務(wù)均可獨(dú)立于其它服務(wù)完成部署,從而達(dá)到更加快速且可持續(xù)性的部署目標(biāo)。 松耦合微服務(wù)提供不同的方式實(shí)現(xiàn)松耦合。每個(gè)微服務(wù)都應(yīng)在服務(wù)級(jí)別有其自身的層級(jí)架構(gòu),并且在使用數(shù)據(jù)庫作為持久層時(shí),它運(yùn)行于自己的獨(dú)立環(huán)境中。 技術(shù)多樣性將微服務(wù)視為隔離的特性,多種技術(shù)的混合可以用于實(shí)現(xiàn)服務(wù)于整體應(yīng)用的多種微服務(wù)。 高效成本服務(wù)實(shí)例可以基于應(yīng)用使用率進(jìn)行優(yōu)化。低價(jià)實(shí)例可以用以最低優(yōu)先的服務(wù),而高價(jià)實(shí)例則可以用到關(guān)鍵業(yè)務(wù)服務(wù)。 性能考慮到微服務(wù)技術(shù)多樣化的優(yōu)點(diǎn),這會(huì)對(duì)性能有直接影響。例如,高阻塞率的服務(wù)調(diào)用在進(jìn)線程技術(shù)棧中實(shí)現(xiàn),CPU密集型服務(wù)在多線程技術(shù)棧中實(shí)現(xiàn)。 和單塊架構(gòu)相比,微服務(wù)也有一些缺點(diǎn)。 諸如,和單塊應(yīng)用相比,開發(fā)和管理分布式應(yīng)用很困難。微服務(wù)需要進(jìn)程間通訊(IPC)機(jī)制以使不同微服務(wù)之間得以通訊,當(dāng)然這可能會(huì)對(duì)性能有點(diǎn)影響(取決于網(wǎng)絡(luò)帶寬)。 以下是為了實(shí)現(xiàn)高效微服務(wù)需要實(shí)現(xiàn)的功能:
自行實(shí)現(xiàn)上述的所有特性是很復(fù)雜的,會(huì)占用大量時(shí)間,并且會(huì)使開發(fā)者消耗大量時(shí)間來開發(fā)和測(cè)試基礎(chǔ)框架配置。然而,如果你已經(jīng)具備了上述的一切,那么你就只需要聚焦于業(yè)務(wù)邏輯了。 Spring Cloud 框架提供了相關(guān)工具在分布式服務(wù)中快速構(gòu)建一些基礎(chǔ)模式,例如配置管理,服務(wù)發(fā)現(xiàn),斷路保護(hù),分布式session,服務(wù)網(wǎng)關(guān),rest客戶端和服務(wù)級(jí)負(fù)載均衡器等。Spring Cloud項(xiàng)目通過在項(xiàng)目中添加一些Maven依賴來完成初始化。這些也可以由使用 spring initialize 的項(xiàng)目創(chuàng)建。 Spring Cloud的許多組件來自Netflix開源軟件中心(Netflix OSS),它們對(duì)于微服務(wù)部署而言是至關(guān)重要的。 Spring Cloud基于Spring Boot構(gòu)建,其中Spring Boot包含了使用最小配置的內(nèi)嵌tomcat服務(wù)器。 如下是在AWS云上使用微服務(wù)的分布式應(yīng)用的架構(gòu)圖。 上述圖例中,我們有3個(gè)不同的微服務(wù),其中主微服務(wù)使用REST客戶端與微服務(wù)A和微服務(wù)B通信。微服務(wù)A運(yùn)行于2個(gè)容器中,微服務(wù)B運(yùn)行于同一實(shí)例的2個(gè)容器中。主微服務(wù)暴露給客戶端,會(huì)通過服務(wù)客戶端與任何微服務(wù)A或微服務(wù)B的實(shí)例互動(dòng),這個(gè)客戶端是一款負(fù)載均衡器。這將會(huì)使得負(fù)載均衡不僅存在于實(shí)例級(jí)別,更存在于同一實(shí)例的服務(wù)級(jí)別。這就是所謂的服務(wù)級(jí)負(fù)載均衡。當(dāng)向一個(gè)服務(wù)發(fā)送請(qǐng)求時(shí),客戶端服務(wù)會(huì)通過查詢Eureka服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)取得服務(wù)實(shí)例的地址。 Spring Cloud已經(jīng)支持使用Eureka作為服務(wù)注冊(cè),并且Eureka服務(wù)注冊(cè)可以通過添加 @SpringBootApplication
@EnableEurekaServer
public class EurekaServer {
public static void main(String[] args) {
System.setProperty("spring.config.name", "registration-server");
SpringApplication.run(EurekaServer.class, args);
}
}
用于服務(wù)注冊(cè)的application.yml: eureka:
instance:
hostname: localhost
client: # Not a client, don't register with yourself
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
port: 1111 # HTTP (Tomcat) port
任何微服務(wù)都可以通過添加 eureka:
client:
serviceUrl:
defaultZone: http://localhost:1111/eureka/
fetchRegistry: true
Spring Cloud提供多種進(jìn)程間通訊方式,其中包括外部客戶端和Rest模板。外部客戶端是十分靈巧、干凈以及易于實(shí)現(xiàn)的??梢酝ㄟ^添加 客戶端應(yīng)用必須創(chuàng)建一個(gè)接口,該接口使用 @FeignClient(value = "serviceA")
public interface ServiceClientA {
@RequestMapping(value = "/user/{userId}", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
public UserProfile getUserProfile(
@PathVariable("userId") Integer userId);
}
我們可以通過創(chuàng)建一個(gè)新的類來調(diào)用這些接口方法,ServiceClientBean.java。 @Component
public class ServiceClientBean {
@Autowired
private ServiceClientA serviceClientA;
@HystrixCommand(fallbackMethod = "defaultMethod")
public UserProfile getUserProfile(Integer userId) {
UserProfile user=serviceClientA.getUSerProfile(userId);
return user;
}
public UserProfile defaultMethod() {
return new UserProfile();
}
}
通過在 @EnableFeignClients(basePackageClasses = ServiceClientA.class)
開發(fā)者可以在客戶端和服務(wù)器之間共享相同的接口定義,但這會(huì)增加客戶端和服務(wù)器之間的耦合度。 外部客戶端自動(dòng)支持使用Ribbon的負(fù)載均衡。Ribbon是客戶端的負(fù)載均衡器,其對(duì)HTTP和TCP請(qǐng)求提供了大量控制支持。我們可以使用外部屬性 在ServiceClientBean.java中,我們添加了一個(gè) 如果微服務(wù)A無法在限定時(shí)間內(nèi)發(fā)送響應(yīng)或者是干脆直接宕掉,那么Hystrix將會(huì)調(diào)用回滾方法來獲取默認(rèn)的響應(yīng)。 我們可以通過添加Hystrix儀表盤應(yīng)用來查看Hystrix統(tǒng)計(jì)和監(jiān)控。 這里還有一個(gè)稱為Zuul代理的組件,能夠充當(dāng)服務(wù)網(wǎng)關(guān)。上文的架構(gòu)圖例中并沒有提及。服務(wù)網(wǎng)關(guān)內(nèi)部調(diào)用多個(gè)微服務(wù),并將來自這些微服務(wù)的結(jié)果聚合,并返回給客戶端服務(wù)。 Zuul代理內(nèi)部使用Eureka服務(wù)器作為服務(wù)發(fā)現(xiàn),使用Ribbon作為服務(wù)實(shí)例間的負(fù)載均衡。 分布式應(yīng)用需要某種中心化日志框架,這可以通過ELK工具棧來簡(jiǎn)單實(shí)現(xiàn)。 |
|
|