Что такое Эврика
Eureka is a REST (Representational State Transfer) based service that is primarily used in the AWS cloud for locating services for the purpose of load balancing and failover of middle-tier servers. We call this service, the Eureka Server. Eureka also comes with a Java-based client component,the Eureka Client, which makes interactions with the service much easier. The client also has a built-in load balancer that does basic round-robin load balancing. At Netflix, a much more sophisticated load balancer wraps Eureka to provide weighted load balancing based on several factors like traffic, resource usage, error conditions etc to provide superior resiliency.
ЭтоNetflix
Официальная инструкция, если вы не очень владеете английским, можете посмотреть перевод ниже.
Перевод: Eureka — это служба на основе REST (передача репрезентативного состояния), которая в основном используется в облаке AWS для служб определения местоположения для достижения балансировки нагрузки и аварийного переключения серверов среднего уровня. Мы называем эту службу сервером Eureka. Eureka также поставляется с клиентским компонентом на основе Java, Eureka Client, который значительно упрощает взаимодействие со службами. Клиент также имеет встроенный балансировщик нагрузки, который может выполнять базовую циклическую балансировку нагрузки. В Netflix более сложный балансировщик нагрузки использует Eureka, чтобы обеспечить взвешенную балансировку нагрузки на основе множества факторов, таких как трафик, использование ресурсов, условия ошибок и т. д., для превосходной отказоустойчивости.
короче,Eureka
этоNetflix
изПлатформа обнаружения служб.
обнаружение службы: По сути, это «посредник».Во всем процессе есть три роли: поставщик услуг (продажа и аренда жилья), потребители услуг (арендаторы-покупатели) и посредники услуг (жилищные посредники).
поставщики услуг: Это предоставление некоторых услуг, которые он может выполнять внешнему миру.
потребители услуг: это «пользователь», которому необходимо использовать некоторые службы.
сервисный посредник: По сути, это «мост» между поставщиками услуг и потребителями услуг.Поставщики услуг могут зарегистрироваться у посредников услуг, а потребители услуг могут найти услуги у посредников услуг, если им нужно потреблять какие-то услуги (использовать какие-то функции). провайдер, зарегистрированный у брокера услуг.
Есть много компонентов, которые могут выступать в качестве обнаружения службы:Zookeeper
,Consul
,Eureka
Ждать.
Некоторые основные понятия Эврики
Реестр регистрации службы:когда
Eureka
клиент дляEureka Server
При регистрации он предоставляет свои собственные метаданные, такие как IP-адрес, порт, индикатор здоровья URL, домашняя страница и т. Д.Продление услуги Продление:
Eureka
Клиент будет отправлять пульс каждые 30 секунд (по умолчанию), чтобы обновить контракт. Сообщите о продлении контрактаEureka Server
ДолженEureka
Клиент все еще там без проблем. Обычно, еслиEureka Server
Не получено за 90 секундEureka
Обновление клиента, он удаляет экземпляр из своего реестра.Получить реестры Получить реестры:
Eureka
Клиент получает информацию реестра с сервера и кэширует ее локально. Клиенты используют эту информацию, чтобы найти другие службы для совершения удаленных вызовов. Информация в этом списке регистрации периодически обновляется (каждые 30 секунд). Каждый раз, когда возвращается информация списка регистрации, это может быть связано сEureka
Информация кэша клиента отличается,Eureka
Клиент обрабатывает это автоматически. Если по какой-либо причине информация о регистрационном списке не может быть сопоставлена вовремя,Eureka
Затем клиент получает всю информацию реестра.Eureka
Сервер кэширует информацию реестра, весь реестр и информацию каждого приложения сжимает, а сжатое содержимое точно такое же, как и несжатое содержимое.Eureka
клиент иEureka
Серверы могут обмениваться данными в формате JSON/XML. по умолчаниюEureka
Клиент использует сжатиеJSON
формат, чтобы получить информацию о списке регистрации.Сервис не в сети Отменить: клиент Eureka отправляет запрос на отмену на сервер Eureka, когда программа закрывается. После отправки запроса информация об экземпляре клиента удаляется из реестра экземпляров сервера. Этот запрос на выход не выполняется автоматически, он должен вызвать следующее:
DiscoveryManager.getInstance().shutdownComponent();
Услуга Ликвидация Выселение: по умолчанию, когда клиент Eureka не отправляет обновление службы, то есть пульс, на сервер Eureka в течение 90 секунд подряд (3 периода обновления), сервер Eureka удалит экземпляр службы из списка регистрации службы, что то есть услуга будет удалена.
Ссылка изГлубокое понимание Эврики
Мы можем понять это таким образом, и проблема, воплощенная в реальность, такова:проблема агента по недвижимости.
регистрация службы: Арендодатель или владелец дома (поставщикEureka Client Provider
) в посреднике (серверEureka Server
), где регистрируется информация о доме, такая как площадь, цена, местоположение и т. д. (метаданныеmetaData
).
Продление услуги: Арендодатель или владелец дома (поставщикEureka Client Provider
) периодически сообщать посреднику (серверуEureka Server
) Мой дом все еще сдается или продается (продление), посредник (серверEureka Server
) сохранить дом после получения.
Получить информацию о списке регистрации: арендатор или покупатель (потребительEureka Client Consumer
) идем к посреднику (серверуEureka Server
), чтобы получить список всей информации о жилье (список клиентовEureka Client List
), а арендатор или покупатель будет регулярно запрашивать у посредника (сервера) самую свежую информациюEureka Server
), чтобы получить и обновить там локальный список.
сервис в автономном режиме: Арендодатель или владелец дома (поставщикEureka Client Provider
) сообщает посреднику (серверуEureka Server
) Мой дом не будет продан или сдан в аренду, и тогда агент удалит информацию о зарегистрированном доме из списка.
исключение услуги: Арендодатель или владелец дома (поставщикEureka Client Provider
) будет периодически связываться с посредником (серверомEureka Server
) сказать ему, что мой дом все еще сдается и продается (продление), если посредник (серверEureka Server
) давно не получал информацию от провайдера, то агент заберет информацию о его жилье с полки (удаление услуги).
Эврика Архитектура
синийEureka Server
даEureka
Эти три сервера представляют собой кластеры, и они децентрализованы.
зеленыйApplication Client
даEureka
клиент, который может бытьпотребительипровайдер, самый левый — типичный провайдер, которому нужноEureka
Сервер регистрирует себя и отправляет пакеты пульса для обновления, в то время как другие потребители проходятEureka
сервер, чтобы получить информацию о провайдере, чтобы позвонить им
Эврика против зоопарка
- Эврика:Соблюдайте принципы APЧтобы обеспечить доступность,
Eureka
Он не ждет, пока все узлы в кластере получат синхронизированную информацию, он будет предоставлять услуги все время. - Работник зоопарка:В соответствии с принципом CPДля обеспечения согласованности он блокируется до тех пор, пока все узлы не будут синхронизированы.
Эврика общая конфигурация
Конфигурация сервера
eureka:
instance:
hostname: xxxxx # 主机名称
prefer-ip-address: true/false # 注册时显示ip
server:
enableSelfPreservation: true # 启动自我保护
renewalPercentThreshold: 0.85 # 续约配置百分比
Его также необходимо установить в классе запуска Spring Boot.@EnableEurekaServer
Аннотация для включения службы Eureka
Конфигурация клиента
eureka:
client:
register-with-eureka: true/false # 是否向注册中心注册自己
fetch-registry: # 指定此客户端是否能获取eureka注册信息
service-url: # 暴露服务中心地址
defaultZone: http://xxxxxx # 默认配置
instance:
instance-id: xxxxx # 指定当前客户端在注册中心的名称
Использование службы обнаружения для поиска служб (практика)
1. Использование Spring DiscoveryClient
Этот метод используется реже, поскольку не используетRibbon
сделатьбалансировки нагрузкиА разработчики пишут слишком много кода, что не способствует развитию и сопровождению. На самом деле суть в том,DiscoveryClient
чтобы получить список всех экземпляров, а затем получитьservice url
пройти сноваRestTemplate
Сделать удаленный звонок. Если вам интересно, вы можете прочитать четвертую главу «Микросервисы в действии».
Следующие два способа, если вы делаете
Eureka Server
Если вы сгруппируетесь, вы испытаетеRibbon
Сюда привезли функцию балансировки нагрузки, потому что это всего лишь простое введение, если читателям интересно, можете попробовать сами.
2. Используйте Spring DiscoveryClient с включенным RestTemplate
Сначала мы создаем сервер Eureka.
1. Создайте проект `spring boot` и проверьте `Eureka Server`
2. Напишите файл конфигурации
server:
port: 8000
eureka:
instance:
hostname: localhost # 指定Eureka主机
client:
register-with-eureka: false # 是否向服务中心注册自己
fetch-registry: false # 是否能够获取Eureka注册信息
service-url: # 暴露自己的服务中心地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
3. Запустите `Eureka Server` и начните доступ к проекту.
Затем создайте клиент ``Provider`
1. Создайте новый проект и отметьте «web» и «Eureka Discovery Client».
2. Напишите файл конфигурации клиента
server:
port: 9001
spring:
application:
name: provider-application # 指定当前应用名 如果不配置 instance-id 那么此项为客户端在注册中心的名称默认值
eureka:
instance:
instance-id: provider-application # 指定当前客户端在注册中心的名称
client:
service-url:
defaultZone: http://localhost:8000/eureka # 服务中心的地址 就是我们在 Eureka Server 中配置的暴露地址
3. Напишите сервисный код и настройте класс запуска
// 直接在启动类中
@SpringBootApplication
@RestController
public class EurekaProviderApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaProviderApplication.class, args);
}
// 随便编写一个服务代码 主要是给消费者调用的
@RequestMapping(value = "/provider/{id}")
public Map providerMethod(@PathVariable(value = "id")Integer id) {
Map map = new HashMap<>();
map.put(id.toString(), "Provider");
return map;
}
}
Создайте `Потребительский` клиент
1. Создайте новый проект, такой же, как у предыдущего провайдера.
2. Запишите информацию о конфигурации клиента-потребителя
server:
port: 9002
spring:
application:
name: consumer-application
eureka:
client:
service-url:
defaultZone: http://localhost:8000/eureka
3. Напишите логику для вызова кода провайдера и установите класс запуска
@SpringBootApplication
@RestController
public class EurekaConsumerApplication {
// 这个注解告诉spring cloud 创建一个支持 Ribbon 的 RestTemplate
@LoadBalanced
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
@Autowired
RestTemplate restTemplate;
@RequestMapping(value = "/consumer/{id}")
public Map consumerTest(@PathVariable(value = "id")Integer id) {
// 通过带有 Ribbon 功能的 RestTemplate 调用服务
ResponseEntity<Map> responseEntity
// 注意这里的url是提供者的名称
= restTemplate.exchange("http://provider-application/provider/" + id, HttpMethod.GET,
null, Map.class, id);
return responseEntity.getBody();
}
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerApplication.class, args);
}
}
4. Результаты испытаний
3. Используйте «Открыть притворство».
Netflix
изOpen Feign
даSpring
устарелRibbion
изRestTemplate
альтернатива.
Ты сможешьОпределите интерфейс, сопоставленный с сервером на стороне потребителя., тогда ты можешьВызовите службу на стороне поставщика, вызвав метод интерфейса на стороне потребителя.(целевая служба REST), кроме написания определения интерфейса, разработчикам не нужно писать другой код для вызова службы, что в настоящее время является широко используемым решением.
Теперь нам просто нужно внести простую модификацию в потребительский проект выше.
Добавьте зависимость `open Feign` и настройте интерфейс
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
@Service
// 使用@FeignClient表示服务 这里的值是 提供者的名称
@FeignClient("provider-application")
// 这里的值是提供者相应的路径
@RequestMapping("/provider")
public interface FeginService {
// 这里的路径也要和提供者相同 参数也需要一样
@GetMapping("/{id}")
Map providerMethod(@PathVariable(value = "id") int id);
}
Создайте класс реализации `Контроллер`
@RestController
public class FeignController {
// 调用服务
@Autowired
private FeginService feginService;
@RequestMapping(value = "/consumer/{id}")
public Map consumerTest(@PathVariable(value = "id")Integer id) {
return feginService.providerMethod(id);
}
}
Добавлена конфигурация Feign.
# 当然你可以不进行配置 这里不影响主要功能
feign:
client:
config:
default:
connectTimeout: 5000 # 指定Feign客户端连接提供者的超时时限 取决于网络环境
readTimeout: 5000 # 指定Feign客户端从请求到获取到提供者给出的响应的超时时限 取决于业务逻辑运算时间
compression:
request:
enabled: true # 开启对请求的压缩
mime-types: text/xml, application/xml
min-request-size: 2048 # 指定启用压缩的最小文件大小
response:
enabled: true # 开启对响应的压缩
Настроить класс запуска
@SpringBootApplication
@EnableFeignClients // 这里需要使用 @EnableFeignClients 来启用 Feign客户端
public class EurekaConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerApplication.class, args);
}
}
Механизм самозащиты Эврики
когдаEureka Server
в конкретной ситуацииEureka Server
не будет отбирать экземпляры из своего регистрационного списка, то естьEureka
период самосохранения.
Почему самозащита? Представьте, когдаserver
Если у узла есть форс-мажорные причины, такие как сетевой раздел, то он не получитclient
пульс обновления, если сеть сильно колеблется, это может вызватьserver
Поскольку флуктуация сети устраняет все или большую частьClient
. Это то, чего мы не хотим видеть.
такEureka
Будет механизм самозащиты.По умолчанию обновление, полученное в течение 15 минут, ниже 85% от исходного (это коэффициент конфигурации продления выше), тогда будет включена самозащита. этот этапEureka Server
Не будет отбраковывать экземпляры из своего списка даже через 90 секунд.
Анализ некоторого исходного кода Eureka
Вот часть анализа исходного кода, в основном с участиемDiscoveryClient
иInstanceInfoReplicator
два класса.
Выше мы упоминалиSpring
серединаDiscoveryClient
Его можно использовать как службу обнаружения, но это более хлопотно.
пока вNetflix
есть такжеDiscoveryClient
, этот класс более мощный. Давайте посмотрим на его описание в официальной документации.
The class that is instrumental for interactions with Eureka Server.
Eureka Client is responsible for a) Registering the instance with Eureka Server b) Renewalof the lease with Eureka Server c) Cancellation of the lease from Eureka Server during shutdown
Вероятно, это означает, что этот класс является ответственным.Eureka Client
зарегистрироваться, перейти в автономный режим, удалить, обновить, запросить список экземплярови так далее.
Теперь давайте посмотрим, как устроен этот класс.
@Inject
DiscoveryClient(ApplicationInfoManager applicationInfoManager,
EurekaClientConfig config,
AbstractDiscoveryClientOptionalArgs args,
Provider<BackupRegistry> backupRegistryProvider, EndpointRandomizer endpointRandomizer){
// 前面做一些校验和预注册处理
.........省略代码
// 很重要 初始化定时任务
initScheduledTasks();
// 后面做一些其他处理 比如时间日志的打印
.........省略代码
}
Вы можете видеть, что самое главное - позвонитьinitScheduledTasks()
функция, а основная инициализация все еще здесь.
private void initScheduledTasks() {
// 如果定义可以获取实例列表信息
if (clientConfig.shouldFetchRegistry()) {
// registry cache refresh timer
// 这里默认获取的30秒 也就是说这里是
// 客户端每三十秒获取一次实例列表信息的代码实现
int registryFetchIntervalSeconds = clientConfig.getRegistryFetchIntervalSeconds();
int expBackOffBound = clientConfig.getCacheRefreshExecutorExponentialBackOffBound();
scheduler.schedule(
new TimedSupervisorTask(
"cacheRefresh",
scheduler,
cacheRefreshExecutor,
registryFetchIntervalSeconds,
TimeUnit.SECONDS,
expBackOffBound,
new CacheRefreshThread()
),
registryFetchIntervalSeconds, TimeUnit.SECONDS);
}
// 如果是想服务中心注册自己的 则注册自己
if (clientConfig.shouldRegisterWithEureka()) {
// 这是续约
int renewalIntervalInSecs = instanceInfo.getLeaseInfo().getRenewalIntervalInSecs();
int expBackOffBound = clientConfig.getHeartbeatExecutorExponentialBackOffBound();
logger.info("Starting heartbeat executor: " + "renew interval is: {}", renewalIntervalInSecs);
// 发送心跳续约 每10秒一次
// Heartbeat timer
scheduler.schedule(
new TimedSupervisorTask(
"heartbeat",
scheduler,
heartbeatExecutor,
renewalIntervalInSecs,
TimeUnit.SECONDS,
expBackOffBound,
new HeartbeatThread()
),
renewalIntervalInSecs, TimeUnit.SECONDS);
// 这里初始化了 实例信息复制器 很重要
instanceInfoReplicator = new InstanceInfoReplicator(
this,
instanceInfo,
clientConfig.getInstanceInfoReplicationIntervalSeconds(),
2); // burstSize
// 做一些状态上的监听和更新操作
.......省略代码
// 这里启动了实例信息复制器
instanceInfoReplicator.start(clientConfig.getInitialInstanceInfoReplicationIntervalSeconds());
} else {
... 打印注册失败日志
}
}
Мы видим, чтоinitScheduledTasks()
в основномИнициализировать все запланированные задачи,НапримерКак долго получать список информации об экземпляре,Как долго отправлять пакеты сердцебиения,Как часто продлевать,Как долго копировать информацию об изменении экземпляра на сервер eurekaи Т. Д.
У вас могут возникнуть вопросы,Почему тридцать секунд, почему так медленно. Студенты, которые любят читать документы, обнаружат, что чиновник дал некоторые инструкции и рекомендует использовать значения по умолчанию.
1.10. Why Is It so Slow to Register a Service?
Экземпляр также включает в себя периодический пульс в реестре (через serviceUrl клиента) с продолжительностью по умолчанию 30 секунд. Служба недоступна для обнаружения клиентами до тех пор, пока экземпляр, сервер и клиент не будут иметь одни и те же метаданные в их локальный кеш (чтобы это могло занять 3 пульса). Вы можете изменить период, установив eureka.instance.leaseRenewalIntervalInSeconds. Установка значения менее 30 ускоряет процесс подключения клиентов к другим службам. В производстве это вероятно, лучше придерживаться значения по умолчанию из-за предположений о внутренних вычислениях на сервере, которые делают предположения о периоде продления аренды.
Преобразование: преобразование в экземпляр также включает периодические пульсации реестра (через serviceUrl клиента) с продолжительностью по умолчанию 30 секунд.
Служба не может быть обнаружена клиентом до тех пор, пока экземпляр, сервер и клиент не будут иметь одни и те же метаданные в своем локальном кэше (поэтому может потребоваться 3 такта).
Вы можете изменить период, установив eureka.instance.leaseRenewalIntervalInSeconds.
Установка значения меньше 30 ускоряет процесс подключения клиентов к другим службам.
В рабочей среде лучше использовать значение по умолчанию, поскольку внутренние расчеты на сервере делают предположения о сроке продления аренды.
В конце также называетсяInstanceInfoReplicator
Метод запуска этого класса и передача информации об изменении экземпляра начальной репликации на временной интервал сервера eureka (40 с), мы продолжаем просматриватьInstanceInfoReplicator
методы этого класса.
public void start(int initialDelayMs) {
// CAS无锁
if (started.compareAndSet(false, true)) {
// 初始化需要40秒
instanceInfo.setIsDirty(); // for initial register
Future next = scheduler.schedule(this, initialDelayMs, TimeUnit.SECONDS);
scheduledPeriodicRef.set(next);
}
}
public void run() {
try {
// 刷新实例信息
discoveryClient.refreshInstanceInfo();
Long dirtyTimestamp = instanceInfo.isDirtyWithTime();
if (dirtyTimestamp != null) {
// 最终还是会调用到 DiscoveryClient 的注册方法
discoveryClient.register();
instanceInfo.unsetIsDirty(dirtyTimestamp);
}
} catch (Throwable t) {
logger.warn("There was a problem with the instance info replicator", t);
} finally {
Future next = scheduler.schedule(this, replicationIntervalSeconds, TimeUnit.SECONDS);
scheduledPeriodicRef.set(next);
}
}
boolean register() throws Throwable {
logger.info(PREFIX + "{}: registering service...", appPathIdentifier);
EurekaHttpResponse<Void> httpResponse;
try {
// 深入里面会调用到 AbstractJerseyEurekaHttpClient 的 注册方法
// 其实里面就是调用到 服务端给客户端暴露出来的 注册接口
httpResponse = eurekaTransport.registrationClient.register(instanceInfo);
} catch (Exception e) {
logger.warn(PREFIX + "{} - registration failed {}", appPathIdentifier, e.getMessage(), e);
throw e;
}
if (logger.isInfoEnabled()) {
logger.info(PREFIX + "{} - registration status: {}", appPathIdentifier, httpResponse.getStatusCode());
}
return httpResponse.getStatusCode() == Status.NO_CONTENT.getStatusCode();
}
Вышеописанный процесс примерно разобрался, если не углубляться, то на самом деле очень просто.
Конечно, метод регистрации, о котором я упоминал выше, на самом деле осуществляется черезRestHttp
Последний звонокEureka Server
Открытый интерфейс регистрации, где этот интерфейс регистрации?
вApplicationResource
серединаaddInstance()
середина
// 这里是暴露了接口
@POST
@Consumes({"application/json", "application/xml"})
public Response addInstance(InstanceInfo info,
@HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication) {
// 做一些日志和校验
.....省略代码
// 到注册中心去注册
registry.register(info, "true".equals(isReplication));
// 返回 204 即无内容的成功
return Response.status(204).build(); // 204 to be backwards compatible
}
В основном все еще здесьregister
метод, последний вызовPeerAwareInstanceImpl
Зарегистрируйте метод в классе.
@Override
public void register(final InstanceInfo info, final boolean isReplication) {
int leaseDuration = Lease.DEFAULT_DURATION_IN_SECS;
if (info.getLeaseInfo() != null && info.getLeaseInfo().getDurationInSecs() > 0) {
leaseDuration = info.getLeaseInfo().getDurationInSecs();
}
// 主要在这里
super.register(info, leaseDuration, isReplication);
// 给同辈进行复制 这其实就是各个节点之间的同步呀
replicateToPeers(Action.Register, info.getAppName(), info.getId(), info, null, isReplication);
}
здесьregister
метод по-прежнему вызываетсяAbstractInstanceRegistry
Метод регистрации в классе, ядро в основном здесь.
Сначала позвольте мне упомянуть,Lease
Среди них объект аренды, который оснащен информацией об экземпляре.(Исходный код является общим держателем).
你可以简单理解为在租房合同中里面记录着房屋的基本信息。
public void register(InstanceInfo registrant, int leaseDuration, boolean isReplication) {
try {
read.lock();
// 这玩意不就有点像注册中心么
// 跟spring的IOC有点相似呀
// 这个registry 是一个 并发hashMap 里面存储了许多实例信息
// 然后 EurekaServer 通过 注册的实例的应用名去获取这个map中获取
// 如果获取到了 说明已经存在了 只需要把它取出来做更新就行
// 否则则新建一个 并做更新
Map<String, Lease<InstanceInfo>> gMap = registry.get(registrant.getAppName());
REGISTER.increment(isReplication);
if (gMap == null) {
。。。省略代码 创建新的gmap
}
.......省略一大堆代码 简单理解也就是更新
// 创建租约
Lease<InstanceInfo> lease = new Lease<InstanceInfo>(registrant, leaseDuration);
if (existingLease != null) {
lease.setServiceUpTimestamp(existingLease.getServiceUpTimestamp());
}
// 这也是更新、、
gMap.put(registrant.getId(), lease);
// 添加到注册队列
synchronized (recentRegisteredQueue) {
recentRegisteredQueue.add(new Pair<Long, String>(
System.currentTimeMillis(),
registrant.getAppName() + "(" + registrant.getId() + ")"));
}
// 进行已覆盖状态的初始状态转移
// 后面涉及到覆盖状态了 不用管先
。。。省略一大堆代码
} finally {
read.unlock();
}
}
Ну, я пропустил много кода.Если вам интересно, вы можете прочитать исходный код и понять принцип в деталях.Здесь я только делаю простой анализ.
чувствовать иSpring
серединаIOC
Регистрация очень похожа, то есть на регистрацию в контейнере, здесь просто смена имени, то есть информация об экземпляре инкапсулируется в контракт, а затем регистрируется в унифицированномMap
Среда (Центр регистрации).
Суммировать
Некоторые вещи в компьютерном мире действительно легко понять, если вы можете думать о них как о примерах из реального мира, таких как автоматические выключатели, балансировка нагрузки и т. д. Можно даже сказать, что решения для многих вещей в компьютере вдохновлены реальным миром. Я не знаю, может ли пример агента по недвижимости, который я привел, сделатьEureka
Сделано это легко понять, но спасибо, что прочитали.
Так как в последнее время я был занят другими делами, у меня меньше времени на написание статей, и я займусь этим позже ヾ(◍°∇°◍)ノ゙.