成人性生交大片免费看视频r_亚洲综合极品香蕉久久网_在线视频免费观看一区_亚洲精品亚洲人成人网在线播放_国产精品毛片av_久久久久国产精品www_亚洲国产一区二区三区在线播_日韩一区二区三区四区区区_亚洲精品国产无套在线观_国产免费www

主頁 > 知識庫 > 通過lms.samples熟悉lms微服務(wù)框架的使用詳解

通過lms.samples熟悉lms微服務(wù)框架的使用詳解

熱門標(biāo)簽:廊坊地圖標(biāo)注申請入口 怎么去掉地圖標(biāo)注文字 高德地圖標(biāo)注公司位置需要錢嗎 慶陽外呼系統(tǒng)定制開發(fā) 合肥阿里辦理400電話號 地圖標(biāo)注資源分享注冊 北京外呼系統(tǒng)咨詢電話 海南人工外呼系統(tǒng)哪家好 襄陽外呼增值業(yè)務(wù)線路解決方案

經(jīng)過一段時間的開發(fā)與測試,終于發(fā)布了Lms框架的第一個正式版本(1.0.0版本),并給出了lms框架的樣例項目lms.samples。本文通過對lms.samples的介紹,簡述如何通過lms框架快速的構(gòu)建一個微服務(wù)的業(yè)務(wù)框架,并進(jìn)行應(yīng)用開發(fā)。

lms.samples項目基本介紹

lms.sample項目由三個獨(dú)立的微服務(wù)應(yīng)用模塊組成:account、stock、order和一個網(wǎng)關(guān)項目gateway構(gòu)成。

業(yè)務(wù)應(yīng)用模塊

每個獨(dú)立的微服務(wù)應(yīng)用采用模塊化設(shè)計,主要由如下幾部分組成:

  1. 主機(jī)(Host): 主要用于托管微服務(wù)應(yīng)用本身,主機(jī)通過引用應(yīng)用服務(wù)項目(應(yīng)用接口的實現(xiàn)),托管微服務(wù)應(yīng)用,通過托管應(yīng)用服務(wù),在主機(jī)啟動的過程中,向服務(wù)注冊中心注冊服務(wù)路由。
  2. 應(yīng)用接口層(Application.Contracts): 用于定義應(yīng)用服務(wù)接口,通過應(yīng)用接口,該微服務(wù)模塊與其他微服務(wù)模塊或是網(wǎng)關(guān)進(jìn)行rpc通信的能力。在該項目中,除了定義應(yīng)用服務(wù)接口之前,一般還定義與該應(yīng)用接口相關(guān)的DTO對象。應(yīng)用接口除了被該微服務(wù)應(yīng)用項目引用,并實現(xiàn)應(yīng)用服務(wù)之前,還可以被網(wǎng)關(guān)或是其他微服務(wù)模塊引用。網(wǎng)關(guān)或是其他微服務(wù)項目通過應(yīng)用接口生成的代理與該微服務(wù)模塊通過rpc進(jìn)行通信。
  3. 應(yīng)用服務(wù)層(Application): 應(yīng)用服務(wù)是該微服務(wù)定義的應(yīng)用接口的實現(xiàn)。應(yīng)用服務(wù)與DDD傳統(tǒng)分層架構(gòu)的應(yīng)用層的概念一致。主要負(fù)責(zé)外部通信與領(lǐng)域?qū)又g的協(xié)調(diào)。一般地,應(yīng)用服務(wù)進(jìn)行業(yè)務(wù)流程控制,但是不包含業(yè)務(wù)邏輯的實現(xiàn)。
  4. 領(lǐng)域?qū)?Domain): 負(fù)責(zé)表達(dá)業(yè)務(wù)概念,業(yè)務(wù)狀態(tài)信息以及業(yè)務(wù)規(guī)則,是該微服務(wù)模塊的業(yè)務(wù)核心。一般地,在該層可以定義聚合根、實體、領(lǐng)域服務(wù)等對象。
  5. 領(lǐng)域共享層(Domain.Shared): 該層用于定義與領(lǐng)域?qū)ο笙嚓P(guān)的模型、實體等相關(guān)類型。不包含任何業(yè)務(wù)實現(xiàn),可以被其他微服務(wù)引用。
  6. 數(shù)據(jù)訪問(DataAccess)層: 該層一般用于封裝數(shù)據(jù)訪問相關(guān)的對象。例如:倉庫對象、 SqlHelper、或是ORM相關(guān)的類型等。在lms.samples中,通過efcore實現(xiàn)數(shù)據(jù)的讀寫操作。

服務(wù)聚合與網(wǎng)關(guān)

lms框架不允許服務(wù)外部與微服務(wù)主機(jī)直接通信,應(yīng)用請求必須通過http請求到達(dá)網(wǎng)關(guān),網(wǎng)關(guān)通過lms提供的中間件解析到服務(wù)條目,并通過rpc與集群內(nèi)部的微服務(wù)進(jìn)行通信。所以,如果服務(wù)需要與集群外部進(jìn)行通信,那么,開發(fā)者定義的網(wǎng)關(guān)必須要引用各個微服務(wù)模塊的應(yīng)用接口層;以及必須要使用lms相關(guān)的中間件。

開發(fā)環(huán)境

  1. .net版本: 5.0.101
  2. lms版本: 1.0.0
  3. IDE: (1) visual studio 最新版 (2) Rider(推薦)

主機(jī)與應(yīng)用托管

主機(jī)的創(chuàng)建步驟

通過lms框架創(chuàng)建一個業(yè)務(wù)模塊非常方便,只需要通過如下4個步驟,就可以輕松的創(chuàng)建一個lms應(yīng)用業(yè)務(wù)模塊。

1.創(chuàng)建項目

創(chuàng)建控制臺應(yīng)用(Console Application)項目,并且引用Silky.Lms.NormHost包。

dotnet add package Silky.Lms.NormHost --version 1.0.0

2.應(yīng)用程序入口與主機(jī)構(gòu)建

main方法中,通用.net的主機(jī)Host構(gòu)建并注冊lms微服務(wù)。在注冊lms微服務(wù)時,需要指定lms啟動的依賴模塊。

一般地,如果開發(fā)者不需要額外依賴其他模塊,也無需在應(yīng)用啟動或停止時執(zhí)行方法,那么您可以直接指定NormHostModule模塊。

 public class Program
    {
        public static async Task Main(string[] args)
        {
            await CreateHostBuilder(args).Build().RunAsync();
        }

        private static IHostBuilder CreateHostBuilder(string[] args)
        {
            return Host.CreateDefaultBuilder(args)
                    .RegisterLmsServicesNormHostModule>()
                ;
        }
    }

3.配置文件

lms框架支持yml或是json格式作為配置文件。通過appsettings.yml對lms框架進(jìn)行統(tǒng)一配置,通過appsettings.${Environment}.yml對不同環(huán)境變量下的配置項進(jìn)行設(shè)置。

開發(fā)者如果直接通過項目的方式啟動應(yīng)用,那么可以通過Properties/launchSettings.jsonenvironmentVariables.DOTNET_ENVIRONMENT環(huán)境變量。如果通過docker-compose的方式啟動應(yīng)用,那么可以通過.env設(shè)置DOTNET_ENVIRONMENT環(huán)境變量。

為保證配置文件有效,開發(fā)者需要顯式的將配置文件拷貝到項目生成目錄下。

4.引用應(yīng)用服務(wù)層和數(shù)據(jù)訪問層

一般地,主機(jī)項目需要引用該微服務(wù)模塊的應(yīng)用服務(wù)層和數(shù)據(jù)訪問層。只有主機(jī)引用應(yīng)用服務(wù)層,主機(jī)在啟動時,才會生成服務(wù)條目的路由,并且將服務(wù)路由注冊到服務(wù)注冊中心。

一個典型的主機(jī)項目文件如下所示:

Project Sdk="Microsoft.NET.Sdk">

    PropertyGroup>
        OutputType>Exe/OutputType>
        TargetFramework>net5.0/TargetFramework>
    /PropertyGroup>

    ItemGroup>
      PackageReference Include="Silky.Lms.NormHost" Version="$(LmsVersion)" />
    /ItemGroup>

    ItemGroup>
      None Update="appsettings.yml">
        CopyToOutputDirectory>Always/CopyToOutputDirectory>
      /None>
      None Update="appsettings.Production.yml">
        CopyToOutputDirectory>Always/CopyToOutputDirectory>
      /None>
      None Update="appsettings.Development.yml">
        CopyToOutputDirectory>Always/CopyToOutputDirectory>
      /None>
    /ItemGroup>

    ItemGroup>
      ProjectReference Include="..\Lms.Account.Application\Lms.Account.Application.csproj" />
      ProjectReference Include="..\Lms.Account.EntityFrameworkCore\Lms.Account.EntityFrameworkCore.csproj" />
    /ItemGroup>
/Project>

配置

一般地,一個微服務(wù)模塊的主機(jī)必須要配置:服務(wù)注冊中心、分布式鎖鏈接、分布式緩存地址、集群rpc通信token、數(shù)據(jù)庫鏈接地址等。

如果使用docker-compose來啟動和調(diào)試應(yīng)用的話,那么,rpc配置節(jié)點(diǎn)下的的host和port可以缺省,因為生成的每個容器的都有自己的地址和端口號。

如果直接通過項目的方式啟動和調(diào)試應(yīng)用的話,那么,必須要配置rpc節(jié)點(diǎn)下的port,每個微服務(wù)模塊的主機(jī)應(yīng)用有自己的端口號。

lms框架的必要配置如下所示:

rpc:
  host: 0.0.0.0
  rpcPort: 2201
  token: ypjdYOzNd4FwENJiEARMLWwK0v7QUHPW
registrycenter:
  connectionStrings: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183;127.0.0.1:2184,127.0.0.1:2185,127.0.0.1:2186 # 使用分號;來區(qū)分不同的服務(wù)注冊中心
  registryCenterType: Zookeeper
distributedCache:
  redis:
    isEnabled: true 
    configuration: 127.0.0.1:6379,defaultDatabase=0
lock:
  lockRedisConnection: 127.0.0.1:6379,defaultDatabase=1
connectionStrings:
    default: server=127.0.0.1;port=3306;database=account;uid=root;pwd=qwe!P4ss;

應(yīng)用接口

應(yīng)用接口定義

一般地,在應(yīng)用接口層開發(fā)者需要安裝Silky.Lms.Rpc包。如果該微服務(wù)模塊還涉及到分布式事務(wù),那么還需要安裝Silky.Lms.Transaction.Tcc,當(dāng)然,您也可以選擇在應(yīng)用接口層安裝Silky.Lms.Transaction包,在應(yīng)用服務(wù)層安裝Silky.Lms.Transaction.Tcc包。

  1. 開發(fā)者只需要在應(yīng)用接口通過ServiceRouteAttribute特性對應(yīng)用接口進(jìn)行直接即可。
  2. Lms約定應(yīng)用接口應(yīng)當(dāng)以IXxxAppService命名,這樣,服務(wù)條目生成的路由則會以api/xxx形式生成。當(dāng)然這并不是強(qiáng)制的。
  3. 每個應(yīng)用接口的方法都對應(yīng)著一個服務(wù)條目,服務(wù)條目的Id為: 方法的完全限定名 + 參數(shù)名
  4. 您可以在應(yīng)用接口層對方法的緩存、路由、服務(wù)治理、分布式事務(wù)進(jìn)行相關(guān)配置。該部分內(nèi)容請參考官方文檔
  5. 網(wǎng)關(guān)或是其他模塊的微服務(wù)項目需要引用服務(wù)應(yīng)用接口項目或是通過nuget的方式安裝服務(wù)應(yīng)用接口生成的包。
  6. [Governance(ProhibitExtranet = true)]可以標(biāo)識一個方法禁止與集群外部進(jìn)行通信,通過網(wǎng)關(guān)也不會生成swagger文檔。
  7. 應(yīng)用接口方法生成的WebApi支持restful API風(fēng)格。Lms支持通過方法的約定命名生成對應(yīng)http方法請求的WebApi。您當(dāng)然開發(fā)者也可以通過HttpMethodAttribute特性對某個方法進(jìn)行注解。

一個典型的應(yīng)用接口的定義

/// summary>
    /// 賬號服務(wù)
    /// /summary>
    [ServiceRoute]
    public interface IAccountAppService
    {
        /// summary>
        /// 新增賬號
        /// /summary>
        /// param name="input">賬號信息/param>
        /// returns>/returns>
        TaskGetAccountOutput> Create(CreateAccountInput input);

        /// summary>
        /// 通過賬號名稱獲取賬號
        /// /summary>
        /// param name="name">賬號名稱/param>
        /// returns>/returns>
        [GetCachingIntercept("Account:Name:{0}")]
        [HttpGet("{name:string}")]
        TaskGetAccountOutput> GetAccountByName([CacheKey(0)] string name);

        /// summary>
        /// 通過Id獲取賬號信息
        /// /summary>
        /// param name="id">賬號Id/param>
        /// returns>/returns>
        [GetCachingIntercept("Account:Id:{0}")]
        [HttpGet("{id:long}")]
        TaskGetAccountOutput> GetAccountById([CacheKey(0)] long id);

        /// summary>
        /// 更新賬號信息
        /// /summary>
        /// param name="input">/param>
        /// returns>/returns>
        [UpdateCachingIntercept( "Account:Id:{0}")]
        TaskGetAccountOutput> Update(UpdateAccountInput input);

        /// summary>
        /// 刪除賬號信息
        /// /summary>
        /// param name="id">賬號Id/param>
        /// returns>/returns>
        [RemoveCachingIntercept("GetAccountOutput","Account:Id:{0}")]
        [HttpDelete("{id:long}")]
        Task Delete([CacheKey(0)]long id);

        /// summary>
        /// 訂單扣款
        /// /summary>
        /// param name="input">/param>
        /// returns>/returns>
        [Governance(ProhibitExtranet = true)]
        [RemoveCachingIntercept("GetAccountOutput","Account:Id:{0}")]
        [Transaction]
        Tasklong?> DeductBalance(DeductBalanceInput input);
    }

應(yīng)用服務(wù)--應(yīng)用接口的實現(xiàn)

  1. 應(yīng)用服務(wù)層只需要引用應(yīng)用服務(wù)接口層以及領(lǐng)域服務(wù)層,并實現(xiàn)應(yīng)用接口相關(guān)的方法。
  2. 確保該微服務(wù)模塊的主機(jī)引用了該模塊的應(yīng)用服務(wù)層,這樣主機(jī)才能夠托管該應(yīng)用本身。
  3. 應(yīng)用服務(wù)層可以通過引用其他微服務(wù)模塊的應(yīng)用接口層項目(或是安裝nuget包,取決于開發(fā)團(tuán)隊的項目管理方法),與其他微服務(wù)模塊進(jìn)行rpc通信。
  4. 應(yīng)用服務(wù)層需要依賴領(lǐng)域服務(wù),通過調(diào)用領(lǐng)域服務(wù)的相關(guān)接口,實現(xiàn)該模塊的核心業(yè)務(wù)邏輯。
  5. DTO到實體對象或是實體對DTO對象的映射關(guān)系可以在該層指定映射關(guān)系。

一個典型的應(yīng)用服務(wù)的實現(xiàn)如下所示:

public class AccountAppService : IAccountAppService
    {
        private readonly IAccountDomainService _accountDomainService;

        public AccountAppService(IAccountDomainService accountDomainService)
        {
            _accountDomainService = accountDomainService;
        }

        public async TaskGetAccountOutput> Create(CreateAccountInput input)
        {
            var account = input.MapToDomain.Accounts.Account>();
            account = await _accountDomainService.Create(account);
            return account.MapToGetAccountOutput>();
        }

        public async TaskGetAccountOutput> GetAccountByName(string name)
        {
            var account = await _accountDomainService.GetAccountByName(name);
            return account.MapToGetAccountOutput>();
        }

        public async TaskGetAccountOutput> GetAccountById(long id)
        {
            var account = await _accountDomainService.GetAccountById(id);
            return account.MapToGetAccountOutput>();
        }

        public async TaskGetAccountOutput> Update(UpdateAccountInput input)
        {
            var account = await _accountDomainService.Update(input);
            return account.MapToGetAccountOutput>();
        }

        public Task Delete(long id)
        {
            return _accountDomainService.Delete(id);
        }

        [TccTransaction(ConfirmMethod = "DeductBalanceConfirm", CancelMethod = "DeductBalanceCancel")]
        public async Tasklong?> DeductBalance(DeductBalanceInput input)
        {
            var account = await _accountDomainService.GetAccountById(input.AccountId);
            if (input.OrderBalance > account.Balance)
            {
                throw new BusinessException("賬號余額不足");
            }
            return await _accountDomainService.DeductBalance(input, TccMethodType.Try);
        }

        public Task DeductBalanceConfirm(DeductBalanceInput input)
        {
            return _accountDomainService.DeductBalance(input, TccMethodType.Confirm);
        }

        public Task DeductBalanceCancel(DeductBalanceInput input)
        {
            return _accountDomainService.DeductBalance(input, TccMethodType.Cancel);
        }
    }

領(lǐng)域?qū)?-微服務(wù)的核心業(yè)務(wù)實現(xiàn)

  1. 領(lǐng)域?qū)邮窃撐⒎?wù)模塊核心業(yè)務(wù)處理的模塊,一般用于定于聚合根、實體、領(lǐng)域服務(wù)、倉儲等業(yè)務(wù)對象。
  2. 領(lǐng)域?qū)右迷撐⒎?wù)模塊的應(yīng)用接口層,方便使用dto對象。
  3. 領(lǐng)域?qū)涌梢酝ㄟ^引用其他微服務(wù)模塊的應(yīng)用接口層項目(或是安裝nuget包,取決于開發(fā)團(tuán)隊的項目管理方法),與其他微服務(wù)模塊進(jìn)行rpc通信。
  4. 領(lǐng)域服務(wù)必須要直接或間接繼承ITransientDependency接口,這樣,該領(lǐng)域服務(wù)才會被注入到ioc容器。
  5. lms.samples 項目使用TanvirArjel.EFCore.GenericRepository包實現(xiàn)數(shù)據(jù)的讀寫操作。

一個典型的領(lǐng)域服務(wù)的實現(xiàn)如下所示:

public class AccountDomainService : IAccountDomainService
    {
        private readonly IRepository _repository;
        private readonly IDistributedCacheGetAccountOutput, string> _accountCache;

        public AccountDomainService(IRepository repository,
            IDistributedCacheGetAccountOutput, string> accountCache)
        {
            _repository = repository;
            _accountCache = accountCache;
        }

        public async TaskAccount> Create(Account account)
        {
            var exsitAccountCount = await _repository.GetCountAsyncAccount>(p => p.Name == account.Name);
            if (exsitAccountCount > 0)
            {
                throw new BusinessException($"已經(jīng)存在{account.Name}名稱的賬號");
            }

            exsitAccountCount = await _repository.GetCountAsyncAccount>(p => p.Email == account.Email);
            if (exsitAccountCount > 0)
            {
                throw new BusinessException($"已經(jīng)存在{account.Email}Email的賬號");
            }

            await _repository.InsertAsyncAccount>(account);
            return account;
        }

        public async TaskAccount> GetAccountByName(string name)
        {
            var accountEntry = _repository.GetQueryableAccount>().FirstOrDefault(p => p.Name == name);
            if (accountEntry == null)
            {
                throw new BusinessException($"不存在名稱為{name}的賬號");
            }

            return accountEntry;
        }

        public async TaskAccount> GetAccountById(long id)
        {
            var accountEntry = _repository.GetQueryableAccount>().FirstOrDefault(p => p.Id == id);
            if (accountEntry == null)
            {
                throw new BusinessException($"不存在Id為{id}的賬號");
            }

            return accountEntry;
        }

        public async TaskAccount> Update(UpdateAccountInput input)
        {
            var account = await GetAccountById(input.Id);
            if (!account.Email.Equals(input.Email))
            {
                var exsitAccountCount = await _repository.GetCountAsyncAccount>(p => p.Email == input.Email);
                if (exsitAccountCount > 0)
                {
                    throw new BusinessException($"系統(tǒng)中已經(jīng)存在Email為{input.Email}的賬號");
                }
            }

            if (!account.Name.Equals(input.Name))
            {
                var exsitAccountCount = await _repository.GetCountAsyncAccount>(p => p.Name == input.Name);
                if (exsitAccountCount > 0)
                {
                    throw new BusinessException($"系統(tǒng)中已經(jīng)存在Name為{input.Name}的賬號");
                }
            }

            await _accountCache.RemoveAsync($"Account:Name:{account.Name}");
            account = input.MapTo(account);
            await _repository.UpdateAsync(account);
            return account;
        }

        public async Task Delete(long id)
        {
            var account = await GetAccountById(id);
            await _accountCache.RemoveAsync($"Account:Name:{account.Name}");
            await _repository.DeleteAsync(account);
        }

        public async Tasklong?> DeductBalance(DeductBalanceInput input, TccMethodType tccMethodType)
        {
            var account = await GetAccountById(input.AccountId);
            var trans = await _repository.BeginTransactionAsync();
            BalanceRecord balanceRecord = null;
            switch (tccMethodType)
            {
                case TccMethodType.Try:
                    account.Balance -= input.OrderBalance;
                    account.LockBalance += input.OrderBalance;
                    balanceRecord = new BalanceRecord()
                    {
                        OrderBalance = input.OrderBalance,
                        OrderId = input.OrderId,
                        PayStatus = PayStatus.NoPay
                    };
                    await _repository.InsertAsync(balanceRecord);
                    RpcContext.GetContext().SetAttachment("balanceRecordId",balanceRecord.Id);
                    break;
                case TccMethodType.Confirm:
                    account.LockBalance -= input.OrderBalance;
                    var balanceRecordId1 = RpcContext.GetContext().GetAttachment("orderBalanceId")?.Tolong>();
                    if (balanceRecordId1.HasValue)
                    {
                        balanceRecord = await _repository.GetByIdAsyncBalanceRecord>(balanceRecordId1.Value);
                        balanceRecord.PayStatus = PayStatus.Payed;
                        await _repository.UpdateAsync(balanceRecord);
                    }
                    break;
                case TccMethodType.Cancel:
                    account.Balance += input.OrderBalance;
                    account.LockBalance -= input.OrderBalance;
                    var balanceRecordId2 = RpcContext.GetContext().GetAttachment("orderBalanceId")?.Tolong>();
                    if (balanceRecordId2.HasValue)
                    {
                        balanceRecord = await _repository.GetByIdAsyncBalanceRecord>(balanceRecordId2.Value);
                        balanceRecord.PayStatus = PayStatus.Cancel;
                        await _repository.UpdateAsync(balanceRecord);
                    }
                    break;
            }

           
            await _repository.UpdateAsync(account);
            await trans.CommitAsync();
            await _accountCache.RemoveAsync($"Account:Name:{account.Name}");
            return balanceRecord?.Id;
        }
    }

數(shù)據(jù)訪問(EntityFrameworkCore)--通過efcore實現(xiàn)數(shù)據(jù)讀寫

  • lms.samples項目使用orm框架efcore進(jìn)行數(shù)據(jù)讀寫。
  • lms提供了IConfigureService,通過繼承該接口即可使用IServiceCollection的實例指定數(shù)據(jù)上下文對象和注冊倉庫服務(wù)。
public class EfCoreConfigureService : IConfigureService
    {
        public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
        {
            services.AddDbContextOrderDbContext>(opt =>
                    opt.UseMySql(configuration.GetConnectionString("Default"),
                        ServerVersion.AutoDetect(configuration.GetConnectionString("Default"))))
                .AddGenericRepositoryOrderDbContext>(ServiceLifetime.Transient)
                ;
        }

        public int Order { get; } = 1;
    }

3.主機(jī)項目需要顯式的引用該項目,只有這樣,該項目的ConfigureServices才會被調(diào)用。

4.數(shù)據(jù)遷移,請參考

應(yīng)用啟動與調(diào)試

獲取源碼

1.使用git 克隆lms項目源代碼,lms.samples存放在samples目錄下

# github
git clone https://github.com/liuhll/lms.git

# gitee
git clone https://gitee.com/liuhll2/lms.git

必要的前提

  1. 服務(wù)注冊中心zookeeper
  2. 緩存服務(wù)redis
  3. mysql數(shù)據(jù)庫

如果您電腦已經(jīng)安裝了docker以及docker-compose命令,那么您只需要進(jìn)入samples\docker-compose\infrastr目錄下,打開命令行工作,執(zhí)行如下命令就可以自動安裝zookeeper、redis、mysql等服務(wù):

docker-compose -f .\docker-compose.mysql.yml -f .\docker-compose.redis.yml -f .\docker-compose.zookeeper.yml up -d

數(shù)據(jù)庫遷移

需要分別進(jìn)入到各個微服務(wù)模塊下的EntityFrameworkCore項目(例如:),執(zhí)行如下命令:

dotnet ef database update

例如: 需要遷移account模塊的數(shù)據(jù)庫如下所示:

order模塊和stock模塊與account模塊一致,在服務(wù)運(yùn)行前都需要通過數(shù)據(jù)庫遷移命令生成相關(guān)數(shù)據(jù)庫。

  1. 數(shù)據(jù)庫遷移指定數(shù)據(jù)庫連接地址默認(rèn)指定的是appsettings.Development.yml中配置的,您可以通過修改該配置文件中的connectionStrings.default配置項來指定自己的數(shù)據(jù)庫服務(wù)地址。
  2. 如果沒有dotnet ef命令,則需要通過dotnet tool install --global dotnet-ef安裝ef工具,請[參考] (https://docs.microsoft.com/zh-cn/ef/core/get-started/overview/install)

以項目的方式啟動和調(diào)試

使用visual studio作為開發(fā)工具

進(jìn)入到samples目錄下,使用visual studio打開lms.samples.sln解決方案,將項目設(shè)置為多啟動項目,并將網(wǎng)關(guān)和各個模塊的微服務(wù)主機(jī)設(shè)置為啟動項目,如下圖:

設(shè)置完成后直接啟動即可。

使用rider作為開發(fā)工具進(jìn)入到samples目錄下,使用rider打開lms.samples.sln解決方案,打開各個微服務(wù)模塊下的Properties/launchSettings.json,點(diǎn)擊圖中綠色的箭頭即可啟動項目。

啟動網(wǎng)關(guān)項目后,可以看到應(yīng)用接口的服務(wù)條目生成的swagger api文檔 http://localhost:5000/swagger。

默認(rèn)的環(huán)境變量為: Development,如果需要修改環(huán)境變量的話,可以通過Properties/launchSettings.json下的environmentVariables節(jié)點(diǎn)修改相關(guān)環(huán)境變量,請參考在 ASP.NET Core 中使用多個環(huán)境。

數(shù)據(jù)庫連接、服務(wù)注冊中心地址、以及redis緩存地址和分布式鎖連接等配置項可以通過修改appsettings.Development.yml配置項自定義指定。

以docker-compose的方式啟動和調(diào)試

進(jìn)入到samples目錄下,使用visual studio打開lms.samples.dockercompose.sln解決方案,將docker-compose設(shè)置為啟動項目,即可啟動和調(diào)式。

應(yīng)用啟動成功后,打開: http://127.0.0.1/swagger,即可看到swagger api文檔

以docker-compose的方式啟動和調(diào)試,則指定的環(huán)境變量為:ContainerDev

數(shù)據(jù)庫連接、服務(wù)注冊中心地址、以及redis緩存地址和分布式鎖連接等配置項可以通過修改appsettings.ContainerDev.yml配置項自定義指定,配置的服務(wù)連接地址不允許為: 127.0.0.1或是localhost

測試和調(diào)式

服務(wù)啟動成功后,您可以通過寫入/api/account-post接口和/api/product-post新增賬號和產(chǎn)品,然后通過/api/order-post接口進(jìn)行測試和調(diào)式。

開源地址

github: https://github.com/liuhll/lms

gitee: https://gitee.com/liuhll2/lms

到此這篇關(guān)于通過lms.samples熟悉lms微服務(wù)框架的使用的文章就介紹到這了,更多相關(guān)lms微服務(wù)框架內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • Java從單體架構(gòu)升級到微服務(wù)要注意的一些問題
  • 詳解Java 微服務(wù)架構(gòu)
  • 了解java架構(gòu)之微服務(wù)架構(gòu)—雪崩效應(yīng)
  • golang 實現(xiàn)一個restful微服務(wù)的操作
  • SpringCloud搭建netflix-eureka微服務(wù)集群的過程詳解
  • SpringCloud讓微服務(wù)實現(xiàn)指定程序調(diào)用
  • Spring Cloud Stream微服務(wù)消息框架原理及實例解析
  • 詳解多云架構(gòu)下的JAVA微服務(wù)技術(shù)解析

標(biāo)簽:平頂山 鎮(zhèn)江 綿陽 臺州 鶴崗 商丘 株洲 哈密

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《通過lms.samples熟悉lms微服務(wù)框架的使用詳解》,本文關(guān)鍵詞  通過,lms.samples,熟悉,lms,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《通過lms.samples熟悉lms微服務(wù)框架的使用詳解》相關(guān)的同類信息!
  • 本頁收集關(guān)于通過lms.samples熟悉lms微服務(wù)框架的使用詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    99久久精品国产一区二区三区| 桃花网日韩影视在线观看视频| 狠狠久久五月精品中文字幕| av在线加勒比| 亚洲小视频在线观看| 欧美男男freegayvideosroom| 中文字幕+乱码+中文字幕明步| 久久成年人网站| 国产精品视频a| 一级在线视频| 国产精品一区二区三区久久| 精品一区二区三区在线观看| www欧美激情| 欧美性猛交xx| 欧美精品一区二区三区在线四季| 日本韩国在线视频爽| 日韩精品人妻中文字幕有码| 三级国产在线观看| 成人激情视频免费在线| 久久国产精品久久精品| 欧美日韩中出| xxx一区二区| 日韩av在线免播放器| 欧美国产一区二区三区| 欧美巨乳美女视频| 日本免费三片免费观看| 国产伦精品一区二区三区视频我| 114国产精品久久免费观看| 国产中年熟女高潮大集合| 久久精品国产精品亚洲| 懂色av蜜臀av粉嫩av分享吧最新章节| 久久国产精品影视| 国产亚洲亚洲| 中文字幕日韩三级片| 久久不射影院| 91精品婷婷国产综合久久| 亚洲777理论| 久青青在线观看视频国产| 日本熟伦人妇xxxx| 第一av在线| 欧美h版在线| 六月丁香久久丫| 亚洲人的天堂男人爽爽爽| 老鸭窝毛片一区二区三区| 亚洲午夜久久久久中文字幕久| 成人福利片在线| 中文字幕 在线观看| 国产欧美日本一区视频| 在线观看欧美| 日韩精品在线不卡| 在线高清一区| 色欲久久久天天天综合网| 99久久久无码国产精品性| 亚洲国产精品成人无久久精品| www.亚洲一二| 日本亚洲精品在线观看| 一区二区三区伦理片| av网站手机在线观看| 国产91久久久久| 日韩欧美在线免费| 日本免费网站| bt电影在线| 成年女人免费视频| 伦av综合一区| 视频精品一区二区| 九九热这里有精品视频| 超碰在线电影| 亚洲av少妇一区二区在线观看| 欧美日韩国产精品| 丰满少妇在线观看网站| av在线麻豆| 亚洲av午夜精品一区二区三区| 久久精品蜜桃| 亚洲成人中文字幕| 日韩精品一二区| 一级黄色片在线免费观看| 青娱乐国产在线| 欧美精品第一页在线播放| 国产精品久久久久不卡| 国产在线视频第一页| 美女脱光内衣内裤视频久久网站| 国产精品v欧美精品v日本精品动漫| www.亚洲成人网| 91美女片黄在线观看| 欧美日韩免费观看中文| 日韩最新在线视频| 久久在线免费观看| 午夜一级毛片| 91不卡在线观看| 91香蕉在线| 在线视频xx| 中文字幕精品www乱入免费视频| 精品国产成人av在线免| 成人黄网18免费观看的网站| 亚洲高清福利| 欧美色图免费看| 国产免费黄色一级片| 亚洲国产综合人成综合网站| 你懂的免费在线观看| 精品久久av| 精品176极品一区| 日韩国产一区二区| 九九精品在线视频| 黄色在线视频网| 在线视频亚洲专区| 日韩av在线播放不卡| 男人添女人下部高潮视频在观看| jizz欧美激情18| a级毛片免费高清视频| 国产亚洲欧美一级| 成人做爰66片免费看网站| 成人国产精品日本在线| 精品久久久久久无码国产| 成人午夜精品一区二区三区| 亚洲免费一级片| 日韩欧美国产免费| 天天影院图片亚洲| 亚洲女色av| 久久影院资源站| 国产偷倩在线播放| 免费国产在线精品一区二区三区| 午夜电影网亚洲视频| 怡红院精品视频在线观看极品| 日韩暖暖在线视频| 久久精品女人的天堂av| 欧美综合天天夜夜久久| 欧美日韩精品在线观看视频| 亚洲熟女综合色一区二区三区| 91久久大香伊蕉在人线| 欧美日韩中文在线视频| 91精品一区| 日韩高清不卡av| 精品亚洲aⅴ无码一区二区三区| 在线观看精品视频看看播放| 91蝌蚪porny成人天涯| 日韩欧美二区| 嫩草嫩草嫩草嫩草嫩草| 色香蕉成人二区免费| 久久久一本精品99久久精品66| http;//www.99re视频| 久久黄色免费看| 深田えいみ中文字幕99久久| 最近中文字幕在线mv视频在线| 99久久久国产精品免费调教网站| www.99re7.com| 国产成人高潮免费观看精品| 国产91色综合久久免费分享| 亚洲国产精品suv| 国产传媒国产传媒| 精品一区二区国产| 国产91丝袜在线观看| 欧美绝品在线观看成人午夜影视| 激情视频在线观看免费| 无码人妻aⅴ一区二区三区69岛| 影视先锋久久| 天堂av在线免费观看| 国产一区二区三区精品在线观看| 欧美视频免费播放| 91麻豆精品国产自产在线观看一区| 国产伦精品一区二区三区免费优势| 国产乱子伦精品无码码专区| 亚洲最新视频在线播放| 国产欧美高清| 欧美日韩国产精品一区二区不卡中文| 国产欧美在线观看视频| 侵犯稚嫩小箩莉h文系列小说| 久久综合另类图片小说| 九色视频入口| www中文在线| 亚洲亚洲精品在线观看| av黄色免费网站| 红桃视频 国产| 久久精品最新地址| 可以看污的网站| 国产精品91一区二区| 黄页免费欧美| 噜噜噜久久,亚洲精品国产品| 国产真人无遮挡作爱免费视频| 五月婷婷欧美激情| 蜜桃麻豆影像在线观看| 国产偷国产偷精品高清尤物| 麻豆视频网站在线观看| 岛国片免费观看| 精品国产百合女同互慰| 九色91在线| 国产馆精品极品| 天天摸天天碰天天添| 黄色网页网址在线免费| 美女福利视频一区| 二区三区四区高清视频在线观看| 国产深夜视频在线观看| 丰满熟妇乱又伦| 911国产网站尤物在线观看| 欧美午夜a级限制福利片| 中文字幕一区二区三区在线乱码| 麻豆视频免费看| 精品人伦一区二区三电影| 天堂va欧美ⅴa亚洲va一国产| 欧美性天天影视| 亚洲私人黄色宅男| 91视频在线看| 成功精品影院| 亚洲午夜91| 精品久久久久久久久久中文字幕| 亚洲一二av| www日本在线观看| 精品福利在线导航| 国内高清免费在线视频| 精品午夜视频| 制服丝袜专区在线| 亚洲欧美精品伊人久久| www中文字幕| 国产免播放器视频| 亚洲午夜精品久久久中文影院av| 特级西西人体www高清大胆| 拍拍拍在线观看视频免费| 日韩精品av| 国产精品乱人伦| 中文字幕亚洲综合久久五月天色无吗''| 一片黄亚洲嫩模| 国产精品久久久久久久免费看| 四虎影视av| 免费不卡中文字幕在线| 欧美美女在线观看| 亚洲综合国产精品| 免费毛片一区二区三区久久久| 玖玖精品在线视频| 亚洲一卡二卡三卡四卡无卡久久| 亚洲精品中文在线影院| 日日草天天干| 国产成人综合在线视频| 国产变态拳头交视频一区二区| 成人精品久久一区二区三区| 夜级特黄日本大片_在线| 蜜桃专区在线| 九一精品在线观看| 欧美在线观看视频| 亚洲精品亚洲人成在线观看| 美女国产在线| 2023国产精品久久久精品双| 99热播精品免费| 国产主播一区二区三区四区| 国产专区欧美专区| 黄色aa久久| 日韩高清dvd碟片| 国产偷人视频免费| 国产精品亚洲综合一区在线观看| 亚洲成人手机在线| 美国十次av导航亚洲入口| 日韩欧美亚洲另类制服综合在线| 91一区二区| 欧美性三三影院| 国产一级一级国产| 日韩免费啪啪| 日韩一区二区三区高清| 欧美亚洲一区二区在线观看| 538prom精品视频线放| a视频在线免费看| 欧美久久精品一级黑人c片| 国产福利成人在线| 亚洲午夜国产一区99re久久| 五月天av网站| 国产99精品在线观看| 欧美一级免费播放| 永久免费看片在线观看| 亚洲经典视频| 第一区第二区在线| 欧美贵妇videos办公室| 国产成人精品国内自产拍免费看| 麻豆视频网站在线观看| 亚洲精品在线电影| 国模私拍国内精品国内av| 亚洲一区在线不卡| 国产欧美一区二区精品秋霞影院| 极品粉嫩饱满一线天在线| 天天影院图片亚洲| 国产精品亚洲天堂| 99精品国产在热久久| 中文字幕一区久| 亚洲天堂网视频| 亚洲视频在线观看一区二区三区| 97影视在线观看| 国产成人av在线影院| 欧美日韩免费观看一区=区三区| 免费国产视频| 免费黄色在线视频网站| 欧洲美女和动交zoz0z| 国产亚洲精品久久久久久豆腐| 一区不卡视频| xxxxx在线观看| 国产精品扒开腿爽爽爽视频| 亚洲国产天堂网精品网站| 成人中文字幕在线| 亚洲精品偷拍| 人人爽久久涩噜噜噜网站| 波多野结衣在线网址| av免费在线免费| 精品sm捆绑视频| 美女诱惑黄网站一区| 麻豆一二三区精品蜜桃| 久草视频国产在线| 国产精品欧美一区二区三区| 久久久国产精华液999999| 久热在线视频观看| 国产精品污www一区二区三区| 美女诱惑黄网站一区| 在线免费视频a| 日韩中文字幕在线精品| 国内在线免费视频| 黄色免费网址大全| 一区二区高清免费观看影视大全| 无码av天堂一区二区三区| 亚洲精品久久久久久| 国产又黄又粗又猛又爽的| 国产精品一区三区在线观看| 超碰在线人人干| 在线观看的毛片| 亚洲精品国产九九九| 亚洲一二区视频| 激情欧美成人久久综合小说| 国产精品久久久久久久久久妞妞| 亚洲综合伊人| 国产美女精品视频免费观看| 日韩av午夜在线观看| 精品一二线国产| av在线收看| www.超碰com| 亚洲国产精品成人va在线观看|