免費網(wǎng)站制作公司優(yōu)化網(wǎng)站排名軟件
1.微服務(wù)入門
(1).單體架構(gòu)與分布式架構(gòu)
單體架構(gòu):?將業(yè)務(wù)的所有功能集中在一個項目中開發(fā),打成一個包部署
優(yōu)點:?架構(gòu)簡單、部署成本低 ;?缺點:?耦合度高
項目打包部署到Tomcat,用戶直接訪問。用戶量增加后就多部署幾臺服務(wù)器形成集群。隨著互聯(lián)網(wǎng)發(fā)展、一個APP或Web通常都用有相當(dāng)多的模塊,因此出現(xiàn)了 分布式架構(gòu)
分布式架構(gòu):?根據(jù)業(yè)務(wù)功能對系統(tǒng)進(jìn)行拆分,每個業(yè)務(wù)模塊作為獨立項目開發(fā),稱為一個服務(wù)。
優(yōu)點:?降低服務(wù)耦合、有利于服務(wù)升級拓展 ;
(2).微服務(wù)
微服務(wù)是一種經(jīng)過良好架構(gòu)設(shè)計的分布式架構(gòu)方案,微服務(wù)架構(gòu)特征:
單一職責(zé): 微服務(wù)拆分粒度更小,每一個服務(wù)都對應(yīng)唯一的業(yè)務(wù)能力,做到單一職責(zé),避免重復(fù)業(yè)務(wù)開發(fā)
面向服務(wù): 微服務(wù)對外暴露業(yè)務(wù)接口
(由于不同模塊部署在不同服務(wù)器、無法直接調(diào)用)
自治: 隊獨立、技術(shù)獨立、數(shù)據(jù)獨立、部署獨立
隔離性強: 服務(wù)調(diào)用做好隔離、容錯、降級,避免出現(xiàn)級聯(lián)問題
(避免某個模塊宕機造成影響)
單體架構(gòu)特點?
簡單方便,高度耦合,擴展性差,適合小型項目。例如: 學(xué)生管理系統(tǒng)分布式架構(gòu)特點?
松耦合,擴展性好,但架構(gòu)復(fù)雜,難度大。適合大型互聯(lián)網(wǎng)項目,例如:京東、淘寶微服務(wù):一種良好的分布式架構(gòu)方案
優(yōu)點: 拆分粒度更小、服務(wù)更獨立、耦合度更低缺點:架構(gòu)非常復(fù)雜,運維、監(jiān)控、部署難度提高
2.服務(wù)拆分及遠(yuǎn)程調(diào)用
1.不同微服務(wù),不要重復(fù)開發(fā)相同業(yè)務(wù)
2.微服務(wù)數(shù)據(jù)獨立,不要訪問其它微服務(wù)的數(shù)據(jù)庫
3.微服務(wù)可以將自己的業(yè)務(wù)暴露為接口,供其它微服務(wù)調(diào)用
1.基于RestTemplate發(fā)起的http請求實現(xiàn)遠(yuǎn)程調(diào)用
2.http請求做遠(yuǎn)程調(diào)用是與語言無關(guān)的調(diào)用,只要知道對方的ip、端口、接口路徑、請求參數(shù)即可。
(1).提供者與消費者
服務(wù)提供者:?一次業(yè)務(wù)中,被其它微服務(wù)調(diào)用的服務(wù)。(提供接口給其它微服務(wù))
服務(wù)消費者:?一次業(yè)務(wù)中,調(diào)用其它微服務(wù)的服務(wù)。(調(diào)用其它微服務(wù)提供的接口)
一個服務(wù)既可以是提供者也可以是消費者,要根據(jù)具體的業(yè)務(wù)和情況來判斷
我們服務(wù)在請求服務(wù)的時候,restTemplate訪問的地址是固定的。 可在實際開發(fā)中通常都會有好幾個環(huán)境,開發(fā),測試等等環(huán)境。每個環(huán)境的地址都在變化 因此出現(xiàn)了幾個問題:
1.服務(wù)消費者該如何獲取服務(wù)提供者的地址信息?
2.如果有多個服務(wù)提供者,消費者該如何選擇?
(2).微服務(wù)遠(yuǎn)程調(diào)用Demo
在父模塊指定了父 POM
<parent><groupId>org.springframework.boot</groupId><version>3.1.0</version><artifactId>spring-boot-starter-parent</artifactId></parent>
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db2username: rootpassword: 123456
mybatis:type-aliases-package: com.home.pojoconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplserver:port: 8088
provider實現(xiàn)controller層,services層,和Mapper層,pojo
@RestController
@RequestMapping("/user")
public class userController {@AutowireduserServices userServices;@RequestMapping("/findAll")public usersss findall(){return userServices.findAll();}
}
consumr層只用實現(xiàn)controller層和pojo
@RestController
@RequestMapping("/a")
public class usersssController {@AutowiredRestTemplate restTemplate;@RequestMapping("/b")public usersss findAll(){usersss userssses= restTemplate.getForObject("http://localhost:8088/user/findAll",usersss.class);return userssses;}
}
usersss userssses= restTemplate.getForObject("http://localhost:8088/user/findAll",usersss.class);
3.注冊中心 Spring Cloud Eureka
Spirng Cloud Eureka使用Netflix Eureka來實現(xiàn)服務(wù)注冊與發(fā)現(xiàn)(服務(wù)治理)。它既包含了服務(wù)端組件,也包含了客戶端組件,并且服務(wù)端與客戶端均采用java編寫,所以Eureka主要適用于通過java實現(xiàn)的分布式系統(tǒng),或是JVM兼容語言構(gòu)建的分布式系統(tǒng)。
Eureka服務(wù)端組件:即服務(wù)注冊中心。它同其他服務(wù)注冊中心一樣,支持高可用配置。依托于強一致性提供良好的服務(wù)實例可用性,可以應(yīng)對多種不同的故障場景。
Eureka客戶端組件:主要處理服務(wù)的注冊和發(fā)現(xiàn)??蛻舳朔?wù)通過注冊和參數(shù)配置的方式,嵌入在客戶端應(yīng)用程序的代碼中。在應(yīng)用程序啟動時,Eureka客戶端向服務(wù)注冊中心注冊自身提供的服務(wù),并周期性的發(fā)送心跳來更新它的服務(wù)租約。同時,他也能從服務(wù)端查詢當(dāng)前注冊的服務(wù)信息并把它們緩存到本地,并周期性的刷新服務(wù)狀態(tài)。
注冊中心保存提供者提供的服務(wù)
客戶消費者定期拉去服務(wù)列表,需要的話就調(diào)用服務(wù)提供者,加入IP和端口變化,消費者再拉去一次新的信息即可;
對于注冊中心來說,Client和Services都是我的客戶端,但是等Client調(diào)用Services的時候,Services就是客戶端,Client就是服務(wù)端;
心跳檢測請求是注冊中心用來檢測服務(wù)提供端是否健在的主要依據(jù)
1.?整合注冊中心Eureka
步驟分三步:
-
第一步:搭建eureka服務(wù),創(chuàng)建eureka_server工程
-
第二步:服務(wù)提供者provider_service,注冊到eureka注冊中心
-
第三步:服務(wù)消費者consumer_service,注冊到eureka注冊中心
4.NACOS
4.1 搭建eureka-server工程
1.創(chuàng)建eureka_server的springboot工程。
2.添加依賴
<properties><spring-cloud.version>2022.0.5</spring-cloud.version><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><modelVersion>4.0.0</modelVersion><artifactId>eureka_server</artifactId><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
3.在啟動類EurekaServerApplication聲明當(dāng)前應(yīng)用為Eureka服務(wù)使用@EnableEurekaServer
注解
@SpringBootApplication
@EnableEurekaServer
public class springBootEurekaServer {public static void main(String[] args) {SpringApplication.run(springBootEurekaServer.class,args);}
}
4.編寫配置文件application.yml
server:port: 8080
spring:application:name: consumer
# 注冊中心地址
eureka:client:service-url:defaultZone: http://127.0.0.1:8761/eurekaregistry-fetch-interval-seconds: 30
5.啟動EurekaServerApplication
6.測試訪問地址http://127.0.0.1:8761,如下信息代表訪問成功
4.2 服務(wù)提供者-注冊到eureka
<properties><spring-cloud.version>2022.0.5</spring-cloud.version><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.5</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency> </dependencies> <dependencyManagement><dependencies> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies> </dependencyManagement>
@SpringBootApplication
@EnableDiscoveryClient
public class springBootProvider {public static void main(String[] args) {SpringApplication.run(springBootProvider.class,args);}
}
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db2username: rootpassword: 123456 application:name: providerServer mybatis:type-aliases-package: com.home.pojoconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplserver:port: 8088 #配置eureka注冊中心的地址 # 注冊中心地址 eureka:client:service-url:defaultZone: http://127.0.0.1:8761/eureka # 租約續(xù)約間隔時間,默認(rèn)30秒eureka:instance:lease-renewal-interval-in-seconds: 30
4.3服務(wù)消費者-注冊到eureka
<properties><spring-cloud.version>2022.0.5</spring-cloud.version><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--當(dāng)前的項目,是eureka的客戶端--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>
</dependencies>
<!--SpringCloud,BOM,依賴清單導(dǎo)入,所有依賴管理的坐標(biāo)-->
<dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>
@SpringBootApplication
@EnableDiscoveryClient
public class springBootConsumerStarter {public static void main(String[] args) {SpringApplication.run(springBootConsumerStarter.class,args);}@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}
}
server:port: 8080 spring:application:name: consumer # 注冊中心地址 eureka:client:service-url:defaultZone: http://127.0.0.1:8761/eurekaregistry-fetch-interval-seconds: 30
4.4消費者通過Eureka訪問提供者
@RestController
@RequestMapping("/a")
public class usersssController {@AutowiredRestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;@RequestMapping("/b")public usersss findAll(){
//discoveryClient 可以拉取注冊中心中服務(wù)列表//getInstances(服務(wù)名),當(dāng)前服務(wù)只有1個,返回值是List集合,獲取0索引服務(wù)對象ServiceInstance instance = discoveryClient.getInstances("PROVIDERSERVER").get(0);//instance服務(wù)對象的實例。獲取服務(wù)提供者的IP,端口號String host = instance.getHost();int port = instance.getPort();return restTemplate.getForObject("http://"+host+":"+port+"/user/findAll", usersss.class);}
}
# 租約續(xù)約間隔時間,默認(rèn)30秒
eureka.instance.lease-renewal-interval-in-seconds: 30?
每過30s注冊中心查看服務(wù)端是否續(xù)租
# 每隔多久獲取服務(wù)中心列表,(只讀備份)
eureka.client.registry-fetch-interval-seconds: 30?
每隔30s客戶端拉去服務(wù)列表
5、SpringCloud Alibaba(Nacos)
5.1?Nacos和Eureka的特點
Eureka的優(yōu)點包括:
1、簡單易用:Eureka框架非常簡單易用,便于快速上手和部署。
2、高可用性:Eureka支持多節(jié)點部署,并會自動將失效的節(jié)點剔除,確保整個系統(tǒng)的高可用性和彈性。
3、動態(tài)擴展性:Eureka可以根據(jù)實際需求進(jìn)行擴展,通過添加新的服務(wù)提供者可以很容易地增加應(yīng)用程序的處理能力。
4、易于集成:Eureka可以與Spring Cloud等流行的微服務(wù)框架進(jìn)行無縫集成,從而提供更完善的微服務(wù)體系支持。
Eureka的不足之處:
1、Eureka Server 為單點故障問題,雖然可以通過多節(jié)點部署來優(yōu)化和緩解,但是在高并發(fā)場景下仍可能成為限制系統(tǒng)擴展的瓶頸。
2、Eureka的服務(wù)注冊中心本身也需要高可用環(huán)境,一旦出現(xiàn)問題,可能影響到整個微服務(wù)的正常運行。
Nacos的優(yōu)點包括:
1、高可用性:Nacos支持多節(jié)點部署,通過選舉算法實現(xiàn)了高可用和故障轉(zhuǎn)移能力,在節(jié)點宕機或網(wǎng)絡(luò)異常情況下仍能保證整個系統(tǒng)的穩(wěn)定運行。
2、動態(tài)擴展性:Nacos可以根據(jù)實際需求進(jìn)行快速擴展和縮容,支持集群、多數(shù)據(jù)中心、地域感知等特性。
3、完備的功能支持:Nacos支持服務(wù)注冊與發(fā)現(xiàn)、配置管理、流量管理、DNS解析、存儲KV對等功能,并且提供了Web界面和RESTful API等多種方式來使用這些功能。
4、易于集成:Nacos提供了多種語言和框架的集成方案,并且支持Spring Cloud等流行的微服務(wù)框架。
總的來說,Nacos是一個功能齊全、易于使用和高可用的分布式服務(wù)治理平臺,可以為分布式系統(tǒng)提供高效、穩(wěn)定的運行環(huán)境。
5.2?Nacos消費者
使用SpringBoot創(chuàng)建項目,搭建提供者服務(wù)(user-service)和消費者服務(wù)(consumer-service)。
創(chuàng)建項目user-service
執(zhí)行創(chuàng)建數(shù)據(jù)庫表,sql腳本
搭建三層架構(gòu)Mapper、Service、Controller,創(chuàng)建根據(jù)id查詢用戶接口
配置user-service服務(wù)
啟動2個端口9091、9092服務(wù),并測試服務(wù)user-service
創(chuàng)建項目consumer-service
配置RestTemplate對象,注入Spring容器
搭建service層和controller層,通過RestTemplate對象發(fā)送請求訪問提供者接口
測試消費者服務(wù)consumer-service
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
<!--SpringCloud,BOM,依賴清單導(dǎo)入,所有依賴管理的坐標(biāo)--><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring.cloud.alibaba.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
@RestController
@RequestMapping("user")
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("queryUserById")public User queryUserById(Integer id){return userService.queryUserById(id);}
}
@Service
public class UserServiceImpl implements UserService{@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;@Overridepublic User queryUserById(Integer id) {List<ServiceInstance> instances = discoveryClient.getInstances("provider_user");ServiceInstance serviceInstance = instances.get(0);String url = "http://"+serviceInstance.getHost()+":"+serviceInstance.getPort();System.out.println("url = " + "http://"+url);User user = restTemplate.getForObject(url+"/user/queryUserById?id=" + id, User.class);return user;}
}
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db2username: rootpassword: 123456application:name: providerNacoscloud:nacos:discovery:server-addr: 127.0.0.1:8848 mybatis:type-aliases-package: com.home.pojoconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
5.3 Nacos服務(wù)者
<properties><spring-cloud.version>2022.0.5</spring-cloud.version><spring.cloud.alibaba.version>2022.0.0.0</spring.cloud.alibaba.version><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>
@RestController
@RequestMapping("/a")
public class usersssController {@AutowiredRestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;@RequestMapping("/b/{id}")public usersss findAll(@PathVariable("id") Integer id){
//discoveryClient 可以拉取注冊中心中服務(wù)列表//getInstances(服務(wù)名),當(dāng)前服務(wù)只有1個,返回值是List集合,獲取0索引服務(wù)對象
// ServiceInstance instance = discoveryClient.getInstances("providerNacos").get(0);//instance服務(wù)對象的實例。獲取服務(wù)提供者的IP,端口號
// String host = instance.getHost();
// int port = instance.getPort();return restTemplate.getForObject("http://providerNacos/user/findAll/"+id, usersss.class);}
}
server:port: 8080 spring:application:name: consumerNacos # 注冊中心地址cloud:nacos:discovery:server-addr: 127.0.0.1:8848
6.負(fù)載均衡
將任務(wù)均勻分配
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>
server:
? port: ${port:9091}
構(gòu)建集群
@RestController
@RequestMapping("/user")
public class userController {@Autowiredhome.services.userServices userServices;@Value("${server.port}")private Integer port;@GetMapping("/findAll/{id}")public usersss findall(@PathVariable("id") Integer id){usersss usersss1= userServices.findAll(id);usersss1.setPort(port);return usersss1;}
}
6.1 修改負(fù)責(zé)均衡算法
public class CustomLoadBalancerConfiguration {
? ? @Bean
? ? ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {
? ? ? ? String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
? ? ? ? return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
? ? }
}
?@Configuration
? ? @LoadBalancerClients(value = {
? ? ? ? ? ? @LoadBalancerClient(name = "providerUser" , configuration = CustomLoadBalancerConfiguration.class) ? ? ?// 將負(fù)載均衡算法應(yīng)用到指定的服務(wù)提供方中
? ? })
? ? public class RestTemplateConfiguration {? ? ? ? @Bean
? ? ? ? @LoadBalanced ? ? ? // 讓RestTemplate具有負(fù)載均衡的能力
? ? ? ? public RestTemplate restTemplate() {
? ? ? ? ? ? return new RestTemplate() ;
? ? ? ? }
}
負(fù)載均衡算法可以改變調(diào)用順序;