軟件架構java
軟件架構是在軟件的內部,通過綜合各類因素的考量、權衡,選擇特定的技術,將系統劃分紅不一樣的部分並使這些部分相互分工,彼此協做,爲用戶提供須要的價值。mysql
軟件架構影響因素golang
業務需求:須要實現的功能 技術棧:選擇用於實現功能的技術 成本:願意爲開發軟件付出的價值 組織架構:有哪些部門能爲開發提供幫助 可擴展性:面向擴展開放 可維護性:維護成本 軟件架構進化web
單體架構面試
單體架構功能、業務集中在一個發佈包裏,部署運行在同一個進程中。redis
優點:易於開發、測試、部署、水平擴展 劣勢:代碼膨脹而難以維護,構建、部署成本大,上手週期長,升級現有技術棧困難,對資源的不一樣需求致使擴展性差 微服務架構spring
使用一套小服務來開發單個應用的方式,每一個服務運行在獨立的進程裏,通常採用輕量級的通信機制互聯,而且它們能夠經過自動化的方式部署。sql
微服務docker
誕生背景數據庫
互聯網行業快速發展 敏捷開發,精益方法深刻人心 容器技術的成熟 特徵
單一職責:只把緊密相關的業務放在一塊兒,無關的業務獨立出去 輕量級通訊:微服務之間的通訊應該是輕量級的,平臺無關,語言無關 隔離性:每一個微服務運行在本身的進程中,不會相互干擾 有本身的數據:有獨立的數據存儲系統 技術多樣性:開發人員選用本身擅長的技術棧 優點
獨立性:微服務構建、部署、擴容、縮容、容錯甚至數據庫都是獨立的 敏捷性:微服務功能單一,API簡單,迭代方便 技術棧靈活:在保證提供穩定服務的狀況下微服務各個模塊能夠自由選擇技術棧 高效團隊:每一個團隊負責本身的微服務,提升開發效率 不足
額外工做:微服務須要考慮如何拆分系統,而單體架構不須要 數據一致性:單體架構可能只有一個數據庫,經過事務能夠保證數據一致性,而微服務有多個數據庫 溝通成本:服務的提供方和調用方可能屬於多個團隊,增長了溝通成本 微服務架構引入的問題
通信
從通信協議角度考慮
REST API RPC MQ 選擇RPC框架考慮因素
I/O、線程調度模型 序列化方式 是否須要多語言支持 常見RPC框架
dubbo
Dubbo 是一款高性能的RPC框架。註冊中心提供註冊和發現服務,而不提供轉發請求。消費者訂閱提供者在註冊中心註冊的服務,經過接口調用提供者對服務的具體實現。監控中心服務統計消費者和提供者的調用次數、調用時間等,並在彙總後發給註冊中心。
motan
Motan
是新浪微博開源的一個Java RPC框架,目前在微博平臺中已經普遍應用,天天爲數百個服務完成近千億次的調用。
thrift
thrift
是一個跨語言的服務部署框架,經過IDL(Interface Definition Language,接口定義語言)來定義RPC的接口和數據類型,並經過thrift編譯器生成不一樣語言的代碼,並由生成的代碼負責RPC協議層和傳輸層的實現。
grpc
在gRPC裏客戶端應用能夠像調用本地對象同樣直接調用另外一臺不一樣的機器上服務端應用的方法。在服務端實現接口,並運行一個gRPC服務器處理客戶端調用。在客戶端擁有一個存根可以像服務端同樣調用方法。gRPC一樣是跨語言的,使用protobuf進行序列化。
rpc框架對比
發現
客戶端發現
客戶端發現
服務端發現
服務端發現
複製代碼
部署
傳統部署可能經過jenkins腳本上傳代碼來部署,微服務隨着數量增多,傳統部署方式部署困難,須要引入服務編排工具,如Mesos、Docker Swarm、Kubernetes。
分佈式服務實踐
以一個簡單的課程服務爲例,實現用戶登陸、註冊,發送消息驗證碼,查詢課程信息等功能,集成dubbo、thrift、SpringBoot、SpringCloud等框架,並在Docker上進行容器化部署。
服務架構
course-thrift-server:基於thrift(Java),經過TSocket對外提供用戶相關服務。 course-dubbo-server:基於Dubbo,經過註冊中心zookeeper註冊提供的服務。 course-message:基於thrift(golang),經過TSocket對外提供信息相關服務。 course-web:web服務入口,根據業務邏輯進行RPC調用。 course-api-gateway:基於SpringCloud zuul的服務網關,經過REST調用course-web的服務,面向客戶調用。
服務依賴
用戶服務
用戶服務負責查詢和註冊用戶信息,實現thrift文件生成的java接口,並經過TSocket對外暴露服務。
thrift代碼生成
編寫thrift文件( thrift語法 ),下載thrift代碼生成工具,使用命令 thrift --gen java --out ../course-interface/src/main/java user_model.thrift && thrift --gen java --out ../course-interface/src/main/java user_service.thrift 生成thrift類和接口文件。
namespace java com.wch.course.domain.thrift
typedef i32 INT typedef i64 LONG
/**
用戶信息 */ struct UserInfo {
/**
/**
/**
/**
/**
/**
namespace java com.wch.course.service.thrift
include 'user_model.thrift'
typedef i32 INT typedef user_model.UserInfo UserInfo
/**
用戶信息服務 */ service IUserService {
/**
/**
/**
經過TSocket暴露thrift服務
@Slf4j @Component public class ThriftServer {
@Value("${thrift.port}")
private int thriftServicePort;
@Resource
private IUserService.Iface userService;
@PostConstruct
public void startThriftServer() {
TProcessor processor = new IUserService.Processor<>(userService);
TNonblockingServerSocket socket = null;
try {
socket = new TNonblockingServerSocket(thriftServicePort);
} catch (TTransportException e) {
log.error("start thrift server error", e);
}
TNonblockingServer.Args args = new TNonblockingServer.Args(socket);
args.processor(processor);
args.transportFactory(new TFramedTransport.Factory());
args.protocolFactory(new TBinaryProtocol.Factory());
TServer server = new TNonblockingServer(args);
new Thread(new Runnable() {
@Override
public void run() {
log.info("thrift server start on {} ...", thriftServicePort);
server.serve();
}
}).start();
}
複製代碼
}
課程服務
課程服務負責查詢課程信息,實現課程服務並將Dubbo接口註冊到zookeeper。
使用dubbo-spring-boot-starter做爲dubbo與SpringBoot集成的jar包(SpringBoot 1.x版本只支持dubbo-spring-boot-starter 0.1.1)。爲了後期與docker集成,部分參數以佔位符的形式存在,而dubbo-spring-boot-starter的自動配置很早就從配置文件中取固定格式的dubbo配置,此時部分參數仍是佔位符的形式,致使自動配置失敗,所以本項目選擇自定義配置參數名稱,手動編寫部分配置替換自動配置。
服務端 配置文件:
dubbo: scan: basePackages: com.wch.course.service.impl application: name: dubbo-provider provider: port: {registry.address}?client=curator
配置註冊中心和服務項:
@Configuration public class DubboConfig {
@Value("${dubbo.registry}")
private String registry;
@Value("${dubbo.provider.port}")
private int dubboPort;
@Bean
public RegistryConfig registryConfig() {
return new RegistryConfig(registry);
}
@Bean
public ProtocolConfig dubboProtocolConfig() {
return new ProtocolConfig("dubbo", dubboPort);
}
複製代碼
}
web服務
web服務負責根據業務邏輯進行RPC調用,並向外部暴露REST接口。
thrift客戶端
private TServiceClient getService(String host, int port, int timeout, Class<? extends TServiceClient> clazz) throws Exception { TSocket socket = new TSocket(host, port, timeout); TFramedTransport transport = new TFramedTransport(socket); transport.open(); TBinaryProtocol tBinaryProtocol = new TBinaryProtocol(transport); Constructor<? extends TServiceClient> constructor = clazz.getConstructor(TProtocol.class); return constructor.newInstance(tBinaryProtocol); }
public IUserService.Client getUserService() throws Exception { return (IUserService.Client) getService(userServiceHost, userServicePort, timeout, IUserService.Client.class); }
public IMessageService.Client getMessageService() throws Exception { return (IMessageService.Client) getService(messageServiceHost, messageServicePort, timeout, IMessageService.Client.class); }
dubbo客戶端配置
配置文件:
dubbo: application: name: dubbo-consumer registry: zookeeper://${registry.address}?client=curator
配置註冊中心:
@Configuration public class DubboConfig {
@Value("${dubbo.registry}")
private String registry;
@Bean
public RegistryConfig registryConfig() {
return new RegistryConfig(registry);
}
複製代碼
}
APIGateway
APIGateway基於SpringCloud zuul向外暴露REST接口。
配置文件:
zuul: routes: course: path: /course/** url: http://localhost:8080/course-web/course/ user: path: /user/** url: http://localhost:8080/course-web/user/ message: path: /message/** url: http://localhost:8080/course-web/message/
構建docker鏡像
對各服務模塊進行打包後編寫Dockerfile:
FROM openjdk:8-jre-slim LABEL maintainer="wch wch@163.com"
COPY target/course-web-1.0-SNAPSHOT.jar /course-web.jar
ENTRYPOINT ["java", "-jar", "/course-web.jar"]
編寫docker-compose文件
各鏡像構建完成後編寫docker-compose文件來方便編排docker服務。
version: '3'
services: zookeeper: image: zookeeper:3.4.13 networks: - rpc-bridge
redis: image: redis:latest command: - "--appendonly yes" volumes: - d:/docker/redis:/data networks: - component-bridge
mysql: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: admin MYSQL_ROOT_HOST: "%" volumes: - d:/docker/mysql/data:/var/lib/mysql - d:/docker/mysql/conf/my.cnf:/etc/mysql/my.cnf networks: - data-bridge
thrift-server: image: course-thrift-server:1.0 links: - mysql command: - "--spring.profiles.active=prd" - "--rpc.thrift.port=8081" - "--mysql.address=mysql:3306" networks: - rpc-bridge - data-bridge
dubbo-server: image: course-dubbo-server:1.0 links: - zookeeper - mysql command: - "--spring.profiles.active=prd" - "--dubbo.port=8083" - "--registry.address=zookeeper:2181" - "--mysql.address=mysql:3306" networks: - rpc-bridge - data-bridge
web: image: course-web:1.0 links: - redis - zookeeper - thrift-server volumes: - d:/docker/app/logs/course-web:/var/app/logs/course-web command: - "--spring.profiles.active=prd" - "--server.port=8080" - "--thrift.service.user.host=thrift-server" - "--thrift.service.user.port=8081" - "--redis.host=redis" - "--redis.port=6379" - "--registry.address=zookeeper:2181" networks: - rpc-bridge - component-bridge - net-bridge
api-gateway: image: course-api-gateway:1.0 links: - web command: - "--spring.profiles.active=prd" - "--server.port=80" - "--web.host=web" - "--web.port=8080" ports: - 80:80 networks: - net-bridge
networks: net-bridge: driver: bridge component-bridge: driver: bridge data-bridge: driver: bridge rpc-bridge: driver: bridge
運行和管理docker服務
docker-compose up -d
docker-compose up --scale dubbo-server=3 -d
docker-compose down
故障
Docker for Windows暴露鏈接端口
本地使用Docker for Windows,運行docker version命令,客戶端報錯,須要勾選Expose daemon ontcp://localhost:2375 without TLS。
Docker for Windows暴露鏈接端口
Docker for Windows共享本地硬盤設置不生效
修改本地共享安全策略後選擇共享給Docker的硬盤。
Docker本地共享安全設置
Docker選擇共享本地硬盤
MySQL默認禁止遠程鏈接
MySQL默認禁止遠程鏈接,須要配置docker容器鏈接用戶的遠程鏈接權限。
安裝的mysql grant all privileges on . to 'root'@'%' identified by 'pwd'; flush privileges;
SELECT user, host FROM mysql.user;
docker提供的mysql鏡像
docker啓動參數中使用-e MYSQL_ROOT_HOST=%
複製代碼
docker run -d -e MYSQL_ROOT_PASSWORD=pass -e MYSQL_ROOT_HOST=% -p 3307:3306 -v d:/docker/mysql/conf/my.cnf:/etc/mysql/my.cnf -v d:/docker/mysql/data:/var/lib/mysql --name=mysql mysql:5.7
redis-windows默認綁定本地
在redis配置文件中,配置 bind 127.0.0.1 表示redis限制本地鏈接,windows版本默認是開啓的,docker容器進行鏈接時須要註釋此配置、
redis設置密碼錯誤
拉取的redis鏡像默認沒有配置密碼,若配置文件中填寫了密碼進行鏈接會保錯。在上docker版本的配置文件中經過配置默認值,即:
spring.redis.password=
來覆蓋密碼配置。
mysql容器ssl鏈接錯誤
使用java客戶端鏈接mysql容器出錯,seSSL參數修改成false。
若是你想學好JAVA這門技術,也想在IT行業拿高薪,能夠參加咱們的訓練營課程,選擇最適合本身的課程學習,技術大牛親授,8個月後,進入名企拿高薪。咱們的課程內容有:Java工程化、高性能及分佈式、高性能、深刻淺出。高架構。性能調優、Spring,MyBatis,Netty源碼分析和大數據等多個知識點。若是你想拿高薪的,想學習的,想就業前景好的,想跟別人競爭能取得優點的,想進阿里面試但擔憂面試不過的,你均可以來,q羣號爲:180705916 進羣免費領取學習資料。