一、前置知識(shí)
1、在Spring Boot中使用Dubbo?
在pom.xml文件中添加Dubbo相關(guān)依賴:服務(wù)提供者和服務(wù)消費(fèi)者都需要
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.8</version>
</dependency>
1)配置服務(wù)提供者
1、在配置文件中配置Dubbo的相關(guān)信息:
# Dubbo應(yīng)用名稱
dubbo.application.name=forlan-provider
# Dubbo注冊(cè)中心地址
dubbo.registry.address=zookeeper://localhost:2181
# Dubbo服務(wù)協(xié)議
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
2、在服務(wù)提供者的啟動(dòng)類上添加@EnableDubbo注解:
@SpringBootApplication
@EnableDubbo
public class ForlanProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
3、編寫服務(wù)提供者的接口和實(shí)現(xiàn)類:
添加@Service,指定interfaceClass屬性來指定要暴露的接口
public interface HelloService {
String sayHello(String name);
}
@Service(interfaceClass = HelloService.class)
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
return "Hello, " + name + "!";
}
}
2)配置服務(wù)消費(fèi)者
1、在配置文件中配置Dubbo的相關(guān)信息:
# Dubbo應(yīng)用名稱
dubbo.application.name=forlan-consumer
# Dubbo注冊(cè)中心地址
dubbo.registry.address=zookeeper://localhost:2181
# Dubbo服務(wù)協(xié)議
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
2、在服務(wù)消費(fèi)者的啟動(dòng)類上添加@EnableDubbo注解:
添加@Reference注解,聲明對(duì)Dubbo服務(wù)的引用
@SpringBootApplication
@EnableDubbo
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
3、編寫服務(wù)消費(fèi)者的代碼:
@RestController
public class HelloController {
@Reference
private HelloService helloService;
@GetMapping("/hello")
public String sayHello(@RequestParam String name) {
return helloService.sayHello(name);
}
}
2、在Spring Boot中使用Eureka?
1)Eureka服務(wù)器
在pom.xml文件中添加Eureka服務(wù)端依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
添加配置:
# 什么都不配,Eureka服務(wù)的默認(rèn)端口號(hào)是8761
配置Eureka服務(wù)器:在Spring Boot應(yīng)用程序的主類上添加@EnableEurekaServer注解,以將應(yīng)用程序標(biāo)記為Eureka服務(wù)器。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
2)Eureka客戶端
在pom.xml文件中添加Eureka客戶端依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
添加配置:
spring.application.name=forlan
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka
配置Eureka客戶端:在Spring Boot應(yīng)用程序的主類上添加@EnableDiscoveryClient注解,以將應(yīng)用程序標(biāo)記為Eureka客戶端。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class ForlanApplication {
public static void main(String[] args) {
SpringApplication.run(ForlanApplication .class, args);
}
}
完成上述配置后,Spring Boot應(yīng)用程序?qū)⒆鳛镋ureka客戶端注冊(cè)到Eureka服務(wù)器,并且可以通過Eureka服務(wù)器進(jìn)行服務(wù)發(fā)現(xiàn)和負(fù)載均衡。
二、項(xiàng)目代碼分析
Eureka相關(guān)依賴:
<!--服務(wù)器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--客戶端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
Dubbo相關(guān)依賴:
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-bom</artifactId>
<version>2.7.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.1</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
1、Eureka服務(wù)器
1)啟動(dòng)類
加上@EnableEurekaServer,將Spring Boot應(yīng)用程序配置為Eureka Server,使其能夠接收其他服務(wù)實(shí)例的注冊(cè)請(qǐng)求,并維護(hù)服務(wù)實(shí)例的狀態(tài)信息。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
2)配置類
# 客戶端是否注冊(cè)到eureka,默認(rèn)true,這里為false
eureka.client.register-with-eureka=false
# 是否從Eureka服務(wù)器獲取注冊(cè)信息,如果單節(jié)點(diǎn),不需要同步其他節(jié)點(diǎn)數(shù)據(jù),用false
eureka.client.fetch-registry=false
# true:實(shí)例以IP的形式注冊(cè);false:實(shí)例以主機(jī)名的形式注冊(cè)
eureka.instance.preferIpAddress=true
# 客戶端注冊(cè)到的Eureka服務(wù)器地址
eureka.client.serviceUrl.defaultZone=http://localhost:8300/eureka/
#Eureka服務(wù)器中用于清理過期實(shí)例的驅(qū)逐間隔時(shí)間,默認(rèn)5000ms
eureka.server.evictionIntervalTimerInMs=5000
# Eureka服務(wù)器更新響應(yīng)緩存的時(shí)間間隔,服務(wù)器本地會(huì)緩存一份,確保響應(yīng)性能,但又需要確保是最新的,需要定期拉取
eureka.server.responseCacheUpdateIntervalMs=5000
# Eureka服務(wù)器是否使用只讀響應(yīng)緩存,false表示可以對(duì)緩存修改,一般建議false
eureka.server.use-read-only-response-cache=false
# Eureka服務(wù)器是否啟用自我保護(hù)機(jī)制,默認(rèn)true
eureka.server.enable-self-preservation=false
2、Dubbo服務(wù)提供者
1)啟動(dòng)類
加上@EnableDubbo,將Spring Boot應(yīng)用程序配置為Dubbo服務(wù)提供者或消費(fèi)者
@SpringBootApplication
@EnableDubbo
public class ForlanProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ForlanProviderApplication.class, args);
}
}
2)配置類
# Dubbo應(yīng)用名
dubbo.application.name=forlan-provider
# 設(shè)置應(yīng)用日志記錄器,如Log4j、Logback和Java自帶的JUL(Java Util Logging),來記錄Dubbo框架的日志信息
dubbo.application.logger=slf4j
# 掃描注冊(cè)com.forlan包下的所有服務(wù)接口
dubbo.scan.base-packages=com.msedu.study
# Dubbo協(xié)議名稱
dubbo.protocol.name=dubbo
# Dubbo協(xié)議端口號(hào)
dubbo.protocol.port=20883
# Dubbo協(xié)議使用的線程池類型為fixed(固定大小線程池)
dubbo.protocol.threadpool=fixed
# Dubbo協(xié)議使用的線程數(shù)量為1000,表示同時(shí)處理的請(qǐng)求數(shù)量
dubbo.protocol.threads=1000
# Dubbo協(xié)議使用的線隊(duì)列長(zhǎng)度為2000,當(dāng)線程數(shù)達(dá)到最大值時(shí),新請(qǐng)求會(huì)被放入任務(wù)隊(duì)列中等待處理
dubbo.protocol.queues=2000
# 服務(wù)提供者的標(biāo)簽,可以設(shè)置不同環(huán)境為不同標(biāo)簽
dubbo.provider.tag=v2.8
# apiVersionFilter 版本過濾器,保證tag延續(xù)
dubbo.provider.filter=apiVersionFilter,providerFilter
# Dubbo使用的注冊(cè)中心為zookeeper,地址為zk-cs:2181
dubbo.registry.address=zookeeper://zk-cs:2181
# 指定額外的注冊(cè)中心鍵和值
dubbo.registry.extra-keys=default.dubbo.tag
# 使用簡(jiǎn)化的注冊(cè)中心實(shí)現(xiàn)來減少注冊(cè)中心的復(fù)雜性和性能開銷
dubbo.registry.simplified=true
# Dubbo不在啟動(dòng)時(shí)檢查注冊(cè)中心的可用性
dubbo.registry.check=false
# 在Dubbo中,注冊(cè)中心可以按照不同的分組來進(jìn)行管理和區(qū)分,這里指定注冊(cè)中心的分組為 `formal`
dubbo.registry.group=formal
# 省略其它無(wú)關(guān)配置...
標(biāo)簽過濾器
添加過濾器傳遞dubbo.tag,用于標(biāo)識(shí)和區(qū)分不同的服務(wù)
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.common.Constants;
public class ApiVersionFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
String version = invocation.getAttachment("dubbo.tag");
if (StringUtil.isNotEmpty(version)) {
RpcContext.getContext().setAttachment("dubbo.tag", version);
}
Result result = invoker.invoke(invocation);
return result;
}
}
提供者過濾器
在每個(gè)rpc被調(diào)用前執(zhí)行特定邏輯,清空本地線程變量
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
@Activate(group = "provider",value = "providerFilter")
public class ProviderFilter implements Filter{
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
// 清空本地線程變量
ThreadLocalUtil.clearThreadVarible();
Result result = invoker.invoke(invocation);
return result;
}
}
3、Dubbo服務(wù)消費(fèi)方/Eureka客戶端
1)啟動(dòng)類
@SpringBootApplication
@EnableDiscoveryClient
@EnableDubbo
public class ForlanRestApplication {
public static void main(String[] args) {
SpringApplication.run(ForlanRestApplication.class, args);
}
}
@EnableDiscoveryClient的作用:服務(wù)注冊(cè)到服務(wù)注冊(cè)中心,并且能夠發(fā)現(xiàn)其他注冊(cè)的微服務(wù)實(shí)例
@EnableDubbo的作用:?jiǎn)⒂肈ubbo服務(wù),標(biāo)識(shí)該類作為Dubbo服務(wù)的提供者或消費(fèi)者
2)配置類
Eureka相關(guān)
#eureka地址
eureka.client.serviceUrl.defaultZone=http://localhost:8300/eureka/
# 服務(wù)示例的版本號(hào)
eureka.instance.metadata-map.version=v2.8
# true:實(shí)例以IP的形式注冊(cè);false:實(shí)例以主機(jī)名的形式注冊(cè)
eureka.instance.preferIpAddress=true
# Eureka客戶端發(fā)送心跳保持租約的時(shí)間間隔,默認(rèn)30s,這里設(shè)置為3s,即每3秒發(fā)送一次續(xù)約
eureka.instance.leaseRenewalIntervalInSeconds=3
# Eureka客戶端租約到期時(shí)間,默認(rèn)90s,這里設(shè)置為10s,即服務(wù)器10s內(nèi)沒收到心跳,則認(rèn)為該實(shí)例不可用
eureka.instance.leaseExpirationDurationInSeconds=10
# true:客戶端會(huì)從服務(wù)注冊(cè)中心獲取并緩存服務(wù)注冊(cè)表的信息;false:僅使用本地緩存的信息,客戶端默認(rèn)為true
eureka.client.fetchRegistry=true
# 客戶端獲取服務(wù)注冊(cè)表的間隔時(shí)間,即刷新本地緩存時(shí)間間隔,默認(rèn)30s
eureka.client.registryFetchIntervalSeconds=5
一般的話,eureka.instance.leaseExpirationDurationInSeconds設(shè)置為eureka.instance.leaseRenewalIntervalInSeconds的兩倍或更多,以確保在網(wǎng)絡(luò)故障或其他問題時(shí)仍能保持可用
Dubbo相關(guān)
# Dubbo應(yīng)用名
dubbo.application.name=forlan-consumer
# 設(shè)置應(yīng)用日志記錄器,如Log4j、Logback和Java自帶的JUL(Java Util Logging),來記錄Dubbo框架的日志信息
dubbo.application.logger=slf4j
# 掃描注冊(cè)com.forlan包下的所有服務(wù)接口
dubbo.scan.base-packages=com.forlan
# Dubbo協(xié)議名稱
dubbo.protocol.name=dubbo
# Dubbo協(xié)議端口號(hào)
dubbo.protocol.port=20880
# 消費(fèi)者在啟動(dòng)時(shí)是否檢查服務(wù)提供者的可用性,false表示在調(diào)用服務(wù)時(shí)才檢查
dubbo.consumer.check=false
# 消費(fèi)者調(diào)用服務(wù)的超時(shí)時(shí)間,這里設(shè)置為50秒
dubbo.consumer.timeout=50000
# 消費(fèi)者在服務(wù)調(diào)用失敗時(shí)的重試次數(shù),默認(rèn)值為0,表示不進(jìn)行重試
dubbo.consumer.retries=0
# 消費(fèi)者使用的過濾器鏈
dubbo.consumer.filter=consumerFilter,-consumercontext,tagRouterFilter
# Dubbo使用的注冊(cè)中心為zookeeper,地址為zk-cs:2181
dubbo.registry.address=zookeeper://zk-cs:2181
# 指定額外的注冊(cè)中心鍵和值
dubbo.registry.extra-keys=default.dubbo.tag
# 使用簡(jiǎn)化的注冊(cè)中心實(shí)現(xiàn)來減少注冊(cè)中心的復(fù)雜性和性能開銷
dubbo.registry.simplified=true
# Dubbo不在啟動(dòng)時(shí)檢查注冊(cè)中心的可用性
dubbo.registry.check=false
# 在Dubbo中,注冊(cè)中心可以按照不同的分組來進(jìn)行管理和區(qū)分,這里指定注冊(cè)中心的分組為 `formal`
dubbo.registry.group=formal
# 省略其它無(wú)關(guān)配置...
ConsumerFilter
獲取公共參數(shù)(accessToken、requestUUID),從本地線程取,設(shè)置到dubbo接口上下文中
import com.msedu.common.utils.ThreadUtil;
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
@Activate(group = "consumer",value = "consumerFilter")
public class ConsumerFilter implements Filter{
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
Result result = null;
try {
// 調(diào)用dubbo接口前存入上下文參數(shù)
String accessToken = (String) ThreadUtil.get("accessToken");
String requestUUID = (String) ThreadUtil.get("requestUUID");
RpcContext.getContext().setAttachment("accessToken", accessToken);
RpcContext.getContext().setAttachment("requestUUID", requestUUID);
result = invoker.invoke(invocation);
}catch(Exception e) {
throw e;
}
return result;
}
}
TagRouterFilter
項(xiàng)目中配置了-consumercontext,表示移除默認(rèn)的ConsumerContextFilter,用TagRouterFilter替換,之所以要替換,是因?yàn)閐ubbo自帶的過濾器會(huì)在調(diào)用完成之后清理掉Attachments,由于我們需要在Attachments中保留dubbo.tag,否則無(wú)法找到對(duì)應(yīng)的服務(wù),這就是TagRouterFilter的作用,其實(shí)就是保留了tag路由,RpcContext.getContext().setAttachment(“dubbo.tag”, invocation.getAttachment(“dubbo.tag”))
@Activate(group = "consumer", order = -10000)
public class TagRouterFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
RpcContext.getContext().setInvoker(invoker).setInvocation(invocation)
.setLocalAddress(NetUtils.getLocalHost(), 0)
.setRemoteAddress(invoker.getUrl().getHost(), invoker.getUrl().getPort());
if (invocation instanceof RpcInvocation) {
((RpcInvocation) invocation).setInvoker(invoker);
}
try {
RpcContext.removeServerContext();
return invoker.invoke(invocation);
} finally {
RpcContext.getContext().clearAttachments();
}
}
@Override
public Result onResponse(Result result, Invoker<?> invoker, Invocation invocation) {
RpcContext.getServerContext().setAttachments(result.getAttachments());
//保留tag路由
RpcContext.getContext().setAttachment("dubbo.tag", invocation.getAttachment("dubbo.tag"));
return result;
}
}
在Dubbo中,AbstractRouter是一個(gè)抽象類,用于實(shí)現(xiàn)路由策略。它的作用是根據(jù)一定的規(guī)則,決定將請(qǐng)求路由到哪個(gè)服務(wù)提供者。具體的路由策略可以通過繼承AbstractRouter類并實(shí)現(xiàn)其中的方法來自定義。Dubbo提供了多種內(nèi)置的路由策略,如基于標(biāo)簽、基于權(quán)重等。通過配置AbstractRouter的實(shí)現(xiàn)類,可以靈活地控制服務(wù)的路由行為。
三、總結(jié)
在項(xiàng)目中,SpringCloud和Dubbo要配置使用的話,需要兩個(gè)注冊(cè)中心。
- Eureka
網(wǎng)關(guān)和Tomcat(Web應(yīng)用程序)都注冊(cè)到Eureka,主要是為了方便網(wǎng)關(guān)進(jìn)行路由,網(wǎng)關(guān)可以從Eureka獲取服務(wù)的注冊(cè)信息,包括服務(wù)的主機(jī)和端口等信息。這樣,網(wǎng)關(guān)就可以根據(jù)需要將請(qǐng)求路由到相應(yīng)的服務(wù)實(shí)例上,實(shí)現(xiàn)請(qǐng)求的轉(zhuǎn)發(fā)和負(fù)載均衡。同時(shí),通過Eureka的服務(wù)發(fā)現(xiàn)機(jī)制,網(wǎng)關(guān)可以動(dòng)態(tài)地獲取服務(wù)實(shí)例的變化,以便及時(shí)更新路由規(guī)則。這種方式可以提高系統(tǒng)的靈活性和可擴(kuò)展性,使網(wǎng)關(guān)能夠自動(dòng)適應(yīng)服務(wù)實(shí)例的變化。
- Zookeeper
Server(提供服務(wù)或資源給客戶端)注冊(cè)到Zookeeper,一方作為Dubbo服務(wù)提供者,一方作為Dubbo服務(wù)消費(fèi)者,通過Dubbo進(jìn)行調(diào)用。
總的來說,網(wǎng)關(guān)注冊(cè)到Eureka,Web應(yīng)用程序同時(shí)注冊(cè)到Eureka和Zookeeper,一方面是可以通過網(wǎng)關(guān)路由轉(zhuǎn)發(fā)到Web應(yīng)用程序,另一方面是作為Dubbo消費(fèi)者;Server注冊(cè)到Zookeeper作為服務(wù)提供者,也可以作為消費(fèi)者,通過Dubbo調(diào)用其它服務(wù)。
思考題
1、Dubbo可以使用的注冊(cè)中心?
默認(rèn)使用的是Zookeeper作為注冊(cè)中心,還可以使用Nacos、Consul等作為注冊(cè)中心,但不能使用Eureka!
2、Dubbo為什么不能注冊(cè)到Eureka?
Dubbo和Eureka是兩個(gè)不同的服務(wù)注冊(cè)與發(fā)現(xiàn)框架,它們之間的集成并不直接支持。
Dubbo是一個(gè)基于Java的分布式服務(wù)框架,它使用自己的注冊(cè)中心來管理服務(wù)的注冊(cè)和發(fā)現(xiàn)。Dubbo的注冊(cè)中心可以是Zookeeper、Etcd、Consul等。Dubbo的設(shè)計(jì)目標(biāo)是為了提供高性能和低延遲的RPC通信,因此它使用了一些特定的協(xié)議和機(jī)制來實(shí)現(xiàn)這些目標(biāo)。
Eureka是Netflix開源的服務(wù)注冊(cè)與發(fā)現(xiàn)框架,它是基于RESTful風(fēng)格的,主要用于構(gòu)建云原生應(yīng)用和微服務(wù)架構(gòu)。Eureka提供了服務(wù)注冊(cè)、發(fā)現(xiàn)和負(fù)載均衡等功能,并且與Spring Cloud等微服務(wù)框架集成緊密。
由于Dubbo和Eureka的設(shè)計(jì)和實(shí)現(xiàn)方式不同,它們之間的集成并不直接支持。如果你想在使用Dubbo的同時(shí)使用Eureka作為服務(wù)注冊(cè)與發(fā)現(xiàn)框架,你可以考慮使用Spring Cloud Alibaba項(xiàng)目中的Nacos作為注冊(cè)中心,Nacos同時(shí)支持Dubbo和Spring Cloud的服務(wù)注冊(cè)與發(fā)現(xiàn)。這樣可以實(shí)現(xiàn)Dubbo與Eureka的集成。
3、服務(wù)A只注冊(cè)到Eureka,Dubbo服務(wù)提供者B只注冊(cè)到Zookeeper,此時(shí),服務(wù)A可以調(diào)用到B?
不可以,因?yàn)镋ureka和ZooKeeper是兩個(gè)不同的注冊(cè)中心,它們之間的服務(wù)注冊(cè)與發(fā)現(xiàn)是相互獨(dú)立的。服務(wù)A只能通過Eureka注冊(cè)中心獲取到其他通過Eureka注冊(cè)的服務(wù)的地址信息,而無(wú)法獲取到通過ZooKeeper注冊(cè)的服務(wù)B的地址信息。
如果服務(wù)A需要通過Dubbo調(diào)用服務(wù)B,需要服務(wù)A將自己注冊(cè)到Zookeeper,才能拉取到服務(wù)注冊(cè)列表,進(jìn)行Dubbo調(diào)用。
4、Web應(yīng)用程序所在服務(wù)同時(shí)注冊(cè)到了Eureka和Zookeeper中,兩個(gè)獨(dú)立注冊(cè)中心,需要同步機(jī)制來保證一致性?
Eureka的心跳間隔默認(rèn)為30秒,項(xiàng)目中設(shè)置為3s;而Zookeeper的心跳間隔為兩倍的tickTime,默認(rèn)情況下tickTime為2000毫秒(2秒),所以心跳間隔為4秒。兩者的心跳間隔不一致,會(huì)導(dǎo)致服務(wù)狀態(tài)出現(xiàn)短暫的不一致,可以調(diào)整心跳間隔保持一致,也可以需要使用同步處理機(jī)制。
具體方案有:文章來源:http://www.zghlxwxcb.cn/news/detail-801688.html
- 通過監(jiān)聽器機(jī)制:在服務(wù)注冊(cè)時(shí),可以注冊(cè)監(jiān)聽器用于監(jiān)聽Eureka和Zookeeper中的服務(wù)變化。當(dāng)服務(wù)狀態(tài)發(fā)生變化時(shí),監(jiān)聽器可以接收到通知,并更新另一個(gè)注冊(cè)中心中的服務(wù)狀態(tài)。
- 通過定時(shí)任務(wù):定時(shí)任務(wù)可以周期性地檢查Eureka和Zookeeper中的服務(wù)狀態(tài),如果發(fā)現(xiàn)狀態(tài)不一致,則進(jìn)行相應(yīng)的同步操作。
- 通過事件驅(qū)動(dòng):當(dāng)服務(wù)狀態(tài)變化時(shí),Eureka和Zookeeper可以發(fā)布事件通知其他服務(wù)節(jié)點(diǎn),其他節(jié)點(diǎn)通過接收事件來進(jìn)行狀態(tài)同步。
- 雙向注冊(cè)中心同步:在服務(wù)注冊(cè)或狀態(tài)變更時(shí),同時(shí)將變更信息同步到兩個(gè)注冊(cè)中心中,保證雙方的服務(wù)狀態(tài)一致性。
5、項(xiàng)目中為什么同時(shí)使用了兩個(gè)不同的注冊(cè)中心?
一開始項(xiàng)目是分布式系統(tǒng),使用的是Dubbo+Zookeeper,后面改造成了微服務(wù),引入了SpringCloud,它默認(rèn)使用的是Eureka,高可用,集成比較好,雖然選擇Zookeeper也可以,但在舊版本,貌似Zookeeper不支持集成SpringCloud,所以最終同時(shí)存在兩個(gè)注冊(cè)中心。文章來源地址http://www.zghlxwxcb.cn/news/detail-801688.html
6、Web應(yīng)用程序所在服務(wù)為什么要同時(shí)注冊(cè)到了Eureka和Zookeeper?
- 注冊(cè)到Eureka,是為了方便路由轉(zhuǎn)發(fā)
- 注冊(cè)到Zookeeper,是為了通過Dubbo調(diào)用服務(wù)
到了這里,關(guān)于在項(xiàng)目中同時(shí)使用SpringCloud和Dubbo,注冊(cè)中心選用Eureka?的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!