1. 程式人生 > >SpringCLoud實戰微服務之——微服務簡介以及入門使用

SpringCLoud實戰微服務之——微服務簡介以及入門使用

微服務概述

微服務是什麼?微服務解決了什麼問題?微服務有什麼特點?

單體架構是什麼?

一個歸檔包包含了應用所有功能的應用程式,我們通常稱之為單體應用。架構單體應用的架構風格,我們稱之為單體架構,這是一種比較傳統的架構風格。

單體架構存在的缺點:

1.複雜性逐漸變高。
2.技術債務逐漸上升。
3.部署速度逐漸變慢。
4.阻礙技術創新。
5.無法按需收縮。

架構的演進:

1.單體架構
2.SOA
3.微服務

什麼是微服務?

Martin Fowler:簡而言之,微服務架構風格這種開發方法,是以開發一組小型服務的方式來開發一個獨立的應用系統的。其中每個小型服務都執行在自己的程序中,並經常採用HTTP資源API這樣輕量的機制來相互通訊。這些服務圍繞業務功能進行構建,並能通過全自動的部署機制來進行獨立部署。這些微服務可以使用不同的語言來編寫,並且可以使用不同的資料儲存技術。對這些微服務我們僅做最低限度的集中管理。
來自:http://www.martinfowler.com/articles/microservices.html

微服務具備的特性:

1.每個微服務都可獨立執行在自己的程序裡。
2.一系列獨立執行的微服務共同構建起了整個系統。
3.每個服務為獨立的業務開發,一個微服務一般完成某個特定的功能,比如:訂單管理、使用者管理等;
4.微服務之間通過一些輕量級的通訊機制進行通訊,例如通過REST API或者RPC的方法進行呼叫。

微服務的優點:

1.易於開發和維護
2.啟動較快
3.區域性修改容易部署
4.技術棧不受限制
5.按需收縮
6.Devops(即便於各個部門之間相互溝通與協作)

微服務帶來的挑戰:

1.運維要求較高
2.分散式的複雜性
3.介面調整成本高
4.重複勞動
注意:所說的重複勞動是說在各個元件使用不同的技術的情況下出現的,例如工具類的編寫,Model類的編寫。如果所有的元件使用的技術全部都相同,則可以將公共部分打包部署到Maven私服上。

微服務設計原則:

1.單一職責原則
2.服務自治原則
3.輕量級通訊原則
4.介面明確原則

微服務開發框架淺談:

Spring Cloud:http://projects.spring.io/spring-cloud
Dubbo:http://dubbo.io
Dropwizard:http://www.dropwizard.io
Consl、etcd &etc.
現在使用Spring cloud構建微服務是社會發展的趨勢。接著去學習Spring  cloud

Spring cloud是什麼?

Spring cloud並不是雲端計算,它是基於Springboot的一種快速構建分散式系統的工具集。
關於Spring cloud的版本:
大部分Spring的版本是以主版本.次版本.增量版本.里程碑版本的形式命名

Spring cloud的特點

① 約定優於配置
② 開箱即用、快速啟動
③ 適用於各種環境
⑤ 使用輕量級的元件 例如:服務發現Eureka
⑥ 元件支援很豐富,功能很齊全(配置中心、註冊中心、智慧路由)
⑦ 選型中立。例如對於服務發現而言 支援三種元件以供選擇(Eureka、ZooKeeper、Consul)

使用Spring cloud需要的技術儲備:

程式語言:主要是Java,也支援Scala和Groovy
構建工具:可以使用Maven和Gradle。 注意:Maven和Gradle專案可以相互轉化,例如將Maven專案轉為Gradle專案可以在Maven專案根目錄下使用終端命令gradle init --type pom 從而將Maven專案轉為Gradle專案。

技術框架:Spring Boot

入門使用

服務提供者:服務的被呼叫方(即:為其他服務提供服務的服務)

服務消費者:服務的呼叫方(即:依賴其它服務的服務)

俗話說:君子生非異也 善假於物。翻譯原生英文文件太浪費時間和精力了,我也是在網上搜到的一些資料。研究沒問題後發出來,借花獻佛 獻醜了。

編寫一個簡單的程式實現服務消費者和服務提供者:


①首先生成服務提供者專案


② 然後生成服務消費者專案


編寫程式碼後兩個的專案結構如下:


(一)服務提供者程式的編寫

schema.sql (SpringBoot啟動時預設執行classpath下的schema.sql作為建表語句)

drop table user if exists;
create table user(
	id bigint generated by default as identity,
	username varchar(40),
	name varchar(20),
	age int(3),
	balance decimal(10,2),
	primary key(id)
);
data.sql 
insert into user(id,username, name, age, balance) values(1,'user1','張三',10, 100.00);
insert into user(id,username, name, age, balance) values(2,'user2','李四',20, 200.00);
insert into user(id,username, name, age, balance) values(3,'user3','王五',30, 300.00);
insert into user(id,username, name, age, balance) values(4,'user4','趙六',40, 400.00);
insert into user(id,username, name, age, balance) values(5,'user5','孫七',50, 500.00);
insert into user(id,username, name, age, balance) values(6,'user6','勝八',60, 600.00);
User.java
package com.liuxun.cloud.entity;

import java.io.Serializable;
import java.math.BigDecimal;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class User implements Serializable {
	private static final long serialVersionUID = 1L;
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;
	@Column
	private String username;
	@Column
	private String name;
	@Column
	private Short age;
	@Column
	private BigDecimal balance;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Short getAge() {
		return age;
	}

	public void setAge(Short age) {
		this.age = age;
	}

	public BigDecimal getBalance() {
		return balance;
	}

	public void setBalance(BigDecimal balance) {
		this.balance = balance;
	}

}
UserRepository
package com.liuxun.cloud.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.liuxun.cloud.entity.User;

public interface UserRepository extends JpaRepository<User, Long> {

}

UserController

package com.liuxun.cloud.controller;

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 com.liuxun.cloud.entity.User;
import com.liuxun.cloud.repository.UserRepository;

@RestController
public class UserController {

	@Autowired
	private UserRepository userRepository;

	@GetMapping("/simple/{id}")
	public User findById(@PathVariable Long id) {
		return userRepository.findById(id).get();
	}
}
application.yml
server:
  port: 7900
spring:
  jpa:
    generate-ddl: false
    show-sql: true
    hibernate:
      ddl-auto: none
  datasource:
    platform: h2
    schema: classpath:schema.sql #defalut schema.sql
    data: classpath:data.sql 
logging:
  level:
    root: info
    org.hibernate.type.descriptor.sql.BasicBinder: trace #與show-sql 結合列印引數
    org.hibernate.type.descriptor.sql.BasicExtractor: trace #與show-sql 結合列印引數
pom.xml (構建專案時自動生成的)
<?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.liuxun.cloud</groupId>
	<artifactId>microservice-simple-provider-user</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>microservice-simple-provider-user</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>
執行測試結果如下:


(二)服務消費者程式的編寫

User.java

package com.liuxun.cloud.entity;

import java.io.Serializable;
import java.math.BigDecimal;

public class User implements Serializable {
	private static final long serialVersionUID = 1L;
	private Long id;
	private String username;
	private String name;
	private Short age;
	private BigDecimal balance;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Short getAge() {
		return age;
	}

	public void setAge(Short age) {
		this.age = age;
	}

	public BigDecimal getBalance() {
		return balance;
	}

	public void setBalance(BigDecimal balance) {
		this.balance = balance;
	}

}
MovieController.java
package com.liuxun.cloud.controller;

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;

import com.liuxun.cloud.entity.User;

@RestController
public class MovieController {

	@Autowired
	private RestTemplate restTemplate;

	@GetMapping("/movie/{id}")
	public User findById(@PathVariable Long id) {
		return this.restTemplate.getForObject("http://localhost:7900/simple/" + id, User.class);
	}
}
Application.java
package com.liuxun.cloud;

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 MicroserviceSimpleConsumerMovieApplication {

	@Bean
	public RestTemplate restTemplate() {
		return new RestTemplate();
	}

	public static void main(String[] args) {
		SpringApplication.run(MicroserviceSimpleConsumerMovieApplication.class, args);
	}
}
application.yml
server:
  port: 7901
pom.xml
<?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.liuxun.cloud</groupId>
	<artifactId>microservice-simple-consumer-movie</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>microservice-simple-consumer-movie</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<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-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

啟動兩個專案在服務消費者端進行測試通訊是成功呼叫的


注意事項:

預設建表語句指令碼是執行classpath下的schema.sql

預設資料指令碼是執行classpath下的data.sql

這種方法的缺陷:微服務元件之間通訊採用了硬編碼是存在很大弊端的:

①如果各個服務模組之間依賴緊密,當修改依賴模組的埠時都要必須在服務消費者中修改地址

②在負載均衡若使用nginx的話這樣硬編碼會導致配置異常繁瑣

相關推薦

SpringCLoud實戰服務——服務簡介以及入門使用

微服務概述微服務是什麼?微服務解決了什麼問題?微服務有什麼特點?單體架構是什麼?一個歸檔包包含了應用所有功能的應用程式,我們通常稱之為單體應用。架構單體應用的架構風格,我們稱之為單體架構,這是一種比較傳統的架構風格。單體架構存在的缺點:1.複雜性逐漸變高。2.技術債務逐漸上升

Chris Richardson服務翻譯:構建服務服務架構的進程通訊

標記 pac blog ural action 客戶端 靈活 dso 不兼容 Chris Richardson 微服務系列翻譯全7篇鏈接: 微服務介紹 構建微服務之使用API網關 構建微服務之微服務架構的進程通訊(本文) 微服務架構中的服務發現 微服務之事件驅動的數據管理

Consul服務信H5炸金花出租平臺搭建註冊與發現

被調用 config 定義 prot data- value sensu echo 應用程序 服務發現是基於微服務架構的關鍵原則之一。嘗試配置每個客戶端或某種形式的約定可能非常困難,可以非常脆弱。Consul通過HTTP API和DNS提供服務發現服務。Spring Clo

服務Eureka服務發現

當呼叫API或者發起網路通訊的時候,無論如何我們都要知道被呼叫方的IP和服務埠,大部分情況是通過域名和服務埠,事實上基於DNS的服務發現,因為DNS快取、無法自治和其他不利因素的存在,有很多侷限。傳統的DNS方式,都是通過nginx或者其他代理軟體來實現,物理機器的ip和port都是固定的,那麼nginx

服務不同服務間進行介面呼叫

前言:最近在做專案時用到了微服務的架構。本篇文章主要說明微服務之間讓服務進行通訊。 正文:在其他模組進行呼叫user模組的使用者所有資訊。 在業務層實現的程式碼 @FeignClient(value="user",fallback=UserServerFailBack.class) public int

springcloud實戰篇四Eureka-client(服務提供者)叢集建立

下面搭建一個Eureka-client的服務提供者叢集1.三個工程的pom.xml依賴是一樣的,所以就僅貼出一個<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org

SpringCloud微服務實戰分散式服務跟蹤Sleuth

通常一個由客戶端發起的請求會在後端系統中經過多個不同的微服務呼叫來協同產生最後的請求結果,在複雜的微服務架構系統中,幾乎每一個前端請求都會形成一條複雜的分散式服務呼叫鏈路,每條鏈路服務痴線錯誤或者延遲都有可能引起請求的失敗。Spring Cloud Sle

信公眾平臺開發實戰Java版信獲取使用者基本資訊

在關注者與公眾號產生訊息互動後,公眾號可獲得關注者的OpenID(加密後的微訊號,每個使用者對每個公眾號的OpenID是唯一的。對於不同公眾號,同一使用者的openid不同)。 公眾號可通過本介面來根據OpenID獲取使用者基本資訊,包括暱稱、頭像、性別、所在城市、語言和

DNS服務主從服務

res 開始 img oss .com alt 再看 同步 服務器 這裏我們做一下DNS主從服務器的實驗,該實驗是接著之前DNS正反向解析實驗做的,很多步驟在上個實驗已經完成,這裏不再重復。 實驗環境:兩臺linux系統作為主從服務器,主服務器IP地址為192.168.1

springcloud實戰篇一Eureka-server建立

以下是springcloud的官方介紹翻譯Spring Cloud為開發人員提供了快速構建分散式系統中的一些通用模式(例如配置管理,服務發現,斷路器,智慧路由,微代理,控制匯流排,一次性令牌,全域性鎖,領導選舉,分散式 會話,群集狀態)。 分散式系統的協調導致了鍋爐板模式,並

linux服務FTP服務配置

    一:FTP工作原理:                a:主動模式                                   1: 客戶端向服務端發起控制連線 埠號為21。併發送一個自己隨機生成的傳輸埠給伺服器                       

linux入門系列18--Web服務Apache服務1

前面系列文章講解了Linux下通過檔案傳輸、檔案共享、郵件系統來分享和獲取資源,本文講解網路資源獲取和共享的另外一種形式,通過Apache服務程式來提供Web服務。 本文先講解目前主流的Web服務程式以及各自的特點和優勢,然後以Apache服務為例講解Linux下Web網站的部署,並在部署過程中穿插講解SE

linux入門系列18--Web服務Apache服務2

接上一篇文章,在瞭解Apache基本配置以及SELinux相關知識後,繼續演示Apache提供的虛擬主機功能以及訪問控制方式。 如果還沒看上一篇的建議先檢視後再來,上篇文章“linux入門系列18--web服務之apache服務1”。 三、Apache虛擬主機功能 如果早期你部署過網站,相信一定知道虛擬機器主

.net持續整合單元測試篇單元測試簡介以及在visual studio中配置Nunit使用環境

系列目錄 單元測試及測試驅動開發簡介 什麼是單元測試 單元測試是一段自動化的程式碼,這段程式碼呼叫被測試的工作單元,之後對這個單元的單個最終結果的某些假設進行檢驗。單元測試幾乎都是用單元測試框架編寫的。單元測試容易編寫,能快速執行。單元測試可靠、可讀、並且可維護。只要產品程式碼不發生變化,單元測試的結果是

python全棧開發【第一篇】Python簡介以及入門

request lambda sci linu ogl red 控制 ttl 排行 一、python介紹   python的創始人為吉多·範羅蘇姆(Guido van Rossum)。1989年的聖誕節期間,Guido開始寫Python語言的編譯器。Python這個名字,來

服務SpringCloud乾貨(一):SpringCloud簡介

什麼是微服務架構   微服務架構就是系統架構設計的一種風格,它主旨將一個獨立的系統,拆分成各個微服務,各個微服務獨立執行,他們之間通過Http的Restful API進行通訊,拆分出來的微服務是根據原系統高耦合部分進行構建(之後會單獨講解如何拆分微服務),每個微服務 都有自己的資料儲存(涉及到分散式事務的

SpringCloud實戰服務——服務發現與服務註冊(二)-Eureka的簡單使用

服務發現元件Eureka簡介服務發現元件可以使用ZK ,也可以使用Consul,之所以Eureka使用最多有如下的原因導致:① Eureka來自生產環境。② Spring  Cloud對Eureka的支援很好。Eureka簡介:Eureka是Netflix開發的服務發現元件,

SpringCloud實戰服務——Ribbon詳解

自定義RibbonClient如何為服務消費者自定義Ribbon Client?① 程式碼自定義RibbonClient所謂的自定義Ribbon Client的主要作用就是使用自定義配置替代Ribbon預設的負載均衡策略,注意:自定義的Ribbon Client是有針對性的,一般一個自定義的Ribbon Cl

springCloud(1):服務簡介

spring cloud 微服務 一、什麽是微服務微服務架構風格是一種將一個單一應用程序開發為一組小型服務的方法,每個服務運行在自己的進程中,服務間通信采用輕量級通信機制(通常用HTTP資源API)。二、微服務架構特性1、每個微服務可獨立運行在自己的進程裏2、一系列獨立運行的微服務共同構建起整個系

服務springCloud和docker-Eureka(一)

決策 config snap service 每次 entry eas pen end 前言 本文記錄怎麽搭建服務註冊中心eureka,然後打包成docker鏡像,用docker swarm部署eureka集群 1、環境spring boot 1.5.1.RELEASE,是