談談架構演變
單體應用:ALL IN ONE
在之前我們,開發一個應用時,只創建一個項目,把所有的頁面、代碼都放着裏面,把這個項目打成war包部署在tomcat中。
優點:
- 開發測試簡便:由於是一個應用,不存在多個應用之間的互聯互調
- 部署簡便:打一個war包部署在tomcat中,不會給運維帶來太多工作挑戰
- 水平拓展簡便:當應用負載能力差時,只需將相同的這一個應用拷貝到很多個服務器上面,多個服務器同時跑這個項目,通過負載均衡機制提高併發能力
缺點:
- 牽一髮動全身:只要是修改代碼,那麼就得重新部署項目
- 隨着現代軟件應用發展,任何一個應用都可能是一個大型應用,不可能ALL IN ONE,維護和分工困難
微服務
爲了解決上面所說的問題,覺定把項目細化,分出多個模塊,微化服務。每一個服務都是一個可替換可獨立升級的軟件單元,每個軟件單元通過http互聯互調就形成了一個輕量級應用網。這些服務可以通過http或者RPC的方式進行互通。
- 節省了調用資源。
- 每個功能元素的服務都是一個可替換的、可獨立升級的軟件代碼。真正的高內聚、低耦合。
而在微服務階段,面臨的問題如:服務的部署、連橋,服務間調度、負載均衡、服務熔斷、消息隊列等都需要去了解學習。路還很長加油!!!
springboot可以快速的構建一個軟件單元,也就是快速的構建一個獨立的服務。而大型分佈式網絡服務的調用,是有springcloud來完成,實現分佈式
SpringCloud
是一套目前完整的微服務框架,它是是一系列框架的有序集合。它只是將目前各家公司開發的比較成熟、經得起實際考驗的服務框架組合起來,通過SpringBoot風格進行再封裝屏蔽掉了複雜的配置和實現原理,最終給開發者留出了一套簡單易懂、易部署和易維護的分佈式系統開發工具包。它利用Spring Boot的開發便利性巧妙地簡化了分佈式系統基礎設施的開發,如服務發現註冊、配置中心、消息總線、負載均衡、斷路器、數據監控等,都可以用SpringBoot的開發風格做到一鍵啓動和部署。
第一個SpringCloud程序
案例的環境依賴
<?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.baidu</groupId>
<artifactId>cloud-test</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>user-service</module>
<module>consumer-demo</module>
<module>eureka-sever</module>
</modules>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.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>
<spring-cloud.version>Finchley.SR1</spring-cloud.version>
<mapper.starter.version>2.0.3</mapper.starter.version>
<mysql.version>5.1.32</mysql.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- springCloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--通用Mapper啓動器-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>${mapper.starter.version}</version>
</dependency>
<!-- mysqL驅動-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
user-service子服務
作爲服務的提供方。
application.yml配置
server:
port: 8081
#控制日誌級別
logging:
level:
com.baidu: debug
# 數據庫連接信息
spring:
application:
name: user-service
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/spring_study_db?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: admin
#配置mybatis的信息
mybatis:
#pojo別名掃描
type-aliases-package: com.baidu.user.pojo
#加載mybatis映射文件,使用通用Mapper這個就不用了
#mapper-locations: classpath:mapper/*mapper.xml
controller代碼:
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/findById/{id}")
public User findById(@PathVariable("id")Integer id){
return userService.findById(id);
}
@GetMapping("/findAll")
public List<User> findAll(){
return userService.findAll();
}
}
consemer-demo子服務
作爲服務的消費方。
application.yml配置
server:
port: 8082
spring:
application:
name: consumer-server
controller代碼:
@RestController
@Reques tMapp ing ("Consumer")
public class Consume rController [
@Autowired
private RestTemplate restTemplate;
@GetMapping("{id}" )
public User queryById (@PathVariable("id") Long id){
String url = "http: //Localhost: 8081/user/findById/" + id;
User user = restTemplate.getForobject(url, User.class) ;
return user;
}
}
這裏我們通過consemer-demo子服務去調用了user-service子服務。
思考上面代碼問題
簡單回顧一下寫了什麼,有沒有問題?
user-service:對外提供了查詢用戶的接口
consumer:通過RestTemplate訪問 http: //Localhost: 8081/user/findById/{id} 接口,查詢用戶數據
- 存在問題:
●在consumer中, 我們把url地址硬編碼到了代碼中,不方便後期維護
●consumer需要記憶user-service的地址,如果出現變更,可能得不到通知,地址將失效
●consumer不清楚user-service的狀態, 服務宕機也不知道
●user-service只有1臺服務, 不具備高可用性
●即便user-service形成集羣, consumer還需自己實現負載均衡