目錄
- spring cloud(一) 從一個簡單的springboot服務(wù)開始
- spring cloud(二) 起步,集成Eureka服務(wù)發(fā)現(xiàn)
- spring cloud(三)Eureka高可用性+Feign聲明式Rest客戶端
-
spring cloud(四) Eureka配置Httpbasic驗證+Eureka配置詳解
未完待續(xù)
一、 為什么要使用微服務(wù)呢?它相比傳統(tǒng)的單體應(yīng)用有什么優(yōu)缺點呢?
從單體應(yīng)用和微服務(wù)的區(qū)別開始說起吧。簡單來說,傳統(tǒng)的單體應(yīng)用就是把項目所需的全部文件打包在一起,而微服務(wù)指的是將功能拆分成可以獨立運行的服務(wù),分開部署,服務(wù)之間通過一些輕量級的通信機制進行通信,這些服務(wù)一起構(gòu)建器整個系統(tǒng)。單從介紹來看微服務(wù)似乎有故意把簡單的問題復(fù)雜化的嫌疑,但是經(jīng)手過傳統(tǒng)的單體應(yīng)用的小伙伴肯定都深有體會,隨著項目的不斷開發(fā),項目的維護成本越來越高,很多功能相互調(diào)用,牽一發(fā)而動全身。不僅如此,編譯調(diào)試的過程也越來越慢。對于新的需求想用全新的技術(shù)棧提高開發(fā)效率也是非常困難。那么微服務(wù)的出現(xiàn)正是為了解決日益復(fù)雜龐大的單體應(yīng)用所導(dǎo)致的項目維護難,升級難的問題。
那么列舉一下微服務(wù)的優(yōu)點吧:
- 易于開發(fā)和維護:因為一個微服務(wù)通常只專注一個特定的業(yè)務(wù)功能,所以它的業(yè)務(wù)比較清晰,代碼量相對較少,開發(fā)和維護單個微服務(wù)相對簡單。
- 技術(shù)棧不受限:多個微服務(wù)之間通過輕量級的通信機制進行通信,每個微服務(wù)完全可以選擇更適合此項業(yè)務(wù)的技術(shù)棧。
- 更合理利用資源:多個微服務(wù)分開部署,可以針對io密集型的服務(wù),和cpu密集型的服務(wù)部署在特定的服務(wù)器上??舍槍δ硞€特定的服務(wù)升級內(nèi)存或增加節(jié)點。
- 復(fù)用性強: 就像堆積木一樣,通用性強的服務(wù)可以用在多個項目中。
微服務(wù)的確定:
- 運維困難: 更多的服務(wù)意味著需要投入更多的精力去維護項目,與傳統(tǒng)的只需要保證一個服務(wù)正常運行相比,保證成噸的服務(wù)正常運行顯然要更費勁。
- 分布式固有的復(fù)雜性:在分布式系統(tǒng)中,網(wǎng)絡(luò)延遲,分布式事務(wù),服務(wù)之間的容錯等都是技術(shù)挑戰(zhàn)。
- 接口的維護成本高: 微服務(wù)之間通過api進行通信,如果修改某個服務(wù)的api將導(dǎo)致其他使用此api的服務(wù)做出相應(yīng)的調(diào)整。
- 重復(fù)的工作: 一些功能有可能多個服務(wù)都需要,此時可能會多個服務(wù)都實現(xiàn)同樣的功能。
二、 微服務(wù)帶來了曙光,也帶來了挑戰(zhàn),那么應(yīng)對這些挑戰(zhàn)我們需要一些設(shè)計原則
- 單一職責(zé)原則
一個服務(wù)只干一件事了。 - 服務(wù)自治原則
每個服務(wù)得有基本的自理能力吧。開發(fā)、測試、部署、運行都應(yīng)該可以獨立完成。 - 輕量級通信原則
一定要輕啊,帶寬很重要。也要滿足跨平臺的特性,常用的協(xié)議有:REST,AMQP,STOMP,MQTT - 微服務(wù)的粒度
如何確定服務(wù)的邊界這是嘗嘗爭論的焦點。需要考慮的因素很多,如業(yè)務(wù)本身,團隊的情況等等。
三、本系列實現(xiàn)微服務(wù)的技術(shù)選擇
- spring-cloud 可以很好的和springboot一起工作,屬于主流的解決方案,文檔豐富社區(qū)活躍。
- docker 出于方便,快捷以及易用性考慮選擇docker作為微服務(wù)的運行平臺。
四、 先從springboot開始實現(xiàn)一個簡單的服務(wù)間調(diào)用吧
場景介紹: 我們實現(xiàn)兩個服務(wù),一個生產(chǎn)者服務(wù),一個消費者服務(wù)。消費者調(diào)用生產(chǎn)者并獲取一個用戶信息。
技術(shù)選擇:java版本:1.8,springboot版本:2.0.5.RELEASE,ORM:JPA,數(shù)據(jù)庫:h2,依賴管理工具:maven,開發(fā)工具:idea
1. 新建一個項目product_server

2. 添加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>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建表語句和data.sql數(shù)據(jù)語句,并添加如下內(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實體
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.編寫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.添加啟動類
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. 運行項目并訪問http://localhost:8080/1

10. 新建一個comsume_server模塊


11. 同上一個項目一樣配置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類
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)建消費者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)建啟動類
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 啟動項目并訪問http://localhost:8000/user/1

到此完成第一個示例的編寫。
五、 談一談上面的示例
完成了一個簡單的微服務(wù)之間調(diào)用,上面這種微服務(wù)的實現(xiàn)方式會面臨什么問題呢?
- 上面的例子中生產(chǎn)者的api是寫死的,當(dāng)生產(chǎn)者的api地址改變時消費者要跟著改變。
- 這種方式服務(wù)的伸縮性比較差,服務(wù)對單個服務(wù)的依賴性較強
- 每次新建一個服務(wù)都要配置api地址心累。
接下來我們開始spring cloud的學(xué)習(xí)吧,看看spring cloud為我們提供的解決方案。敬請期待。