Açıkça yapılandırılmış Go mikro hizmeti: uygulama kapsayıcısı

Yazar | Yitian Coder

Kaynak | CSDN blogu, sorumlu editör | Xi Yan

Üretildi | CSDN (ID: CSDNnews)

Clean Architecture kavramlarından biri, programın çerçevesini izole etmektir, böylece çerçeve uygulamanızı devralmaz, ancak bunları ne zaman ve nerede kullanacağınıza siz karar verirsiniz. Bu programda, başlangıçta kasıtlı olarak herhangi bir çerçeve kullanmıyorum, böylece program yapısını daha iyi kontrol edebilirim. Ancak tüm program yapısı düzeni tamamlandıktan sonra, bu programın bazı bileşenlerini bazı kitaplıklarla değiştirmeyi düşüneceğim. Bu şekilde, sunulan çerçevenin veya üçüncü taraf kitaplığın etkisi, doğru bağımlılıklar tarafından izole edilecektir. Şu anda, logger, veritabanı, gRPC ve Protobuf'a (kaçınılmaz olan) ek olarak, yalnızca iki üçüncü taraf kitaplığı ozzo-validation¹ ve YAML² kullanıyorum ve diğer tüm kitaplıklar Go standart kitaplıklardır.

Bu programı uygulama oluşturma temeli olarak kullanabilirsiniz. Sorabilirsiniz, bu çerçeve tüm uygulamayı devralmayacak mı? Evet. Ancak gerçek şu ki, ister kendi çerçevenizi oluşturun ister üçüncü taraf bir çerçeve sunun, uygulama oluşturmanın temeli olarak temel bir çerçeveye ihtiyacınız var. Vakfın doğru bağımlılıklara ve güvenilir bir tasarıma sahip olması gerekir ve ardından diğer kütüphaneleri açıp açmayacağınıza karar verebilirsiniz. Elbette kendiniz bir çerçeve oluşturabilirsiniz, ancak bunu mükemmelleştirmek için çok fazla zaman ve enerji harcayabilirsiniz. Bu programı kendi projenizi oluşturmak yerine başlangıç noktası olarak da kullanabilir, böylece size zaman ve enerji tasarrufu sağlayabilirsiniz.

Uygulama kabı, projenin en karmaşık parçasıdır ve uygulamanın farklı bölümlerini birbirine yapıştıran anahtar bileşendir. Programın geri kalanı açık ve anlaşılması kolay, ancak bu kısım değil. İyi haber şu ki, bu bölümü anladığınızda tüm program kontrol altında olacak.

"Konteyner" paketinin bileşenleri

Konteyner paketi beş bölümden oluşmaktadır:

1. "Konteyner" paketi: Somut türler oluşturmaktan ve bunları diğer dosyalara enjekte etmekten sorumludur. Üst düzey pakette, konteynerin arayüzünü tanımlayan tek bir dosya "container.go" vardır.

2. "Servicecontainer" alt paketi : Konteyner arayüzünün uygulanması. "Container" paketinin anahtarı olan tek bir dosya "serviceContainer.go" vardır. Aşağıdaki koddur. Başlangıç noktası, bir dosyadan yapılandırma verilerini okuyan ve bir kaydedici kuran "InitApp" dir.

Type ServiceContainer struct { FactoryMap mapinterface {} AppConfig * config.AppConfig} func (sc * ServiceContainer) InitApp (dosya adı dizesi) hatası {var err error config, err: = loadConfig (dosya adı) if err! = nil {return errors.Wrap (err, "loadConfig")} sc.AppConfig = config err = loadLogger (config.Log) eğer err! = nil {return errors.Wrap (err, "loadLogger")} dönüş nil} // loggerfunc loadLogger (lc config.LogConfig) hatasını yükler {loggerType: = lc.Code err: = logFactory.GetLogFactoryBuilder (loggerType) .Build (lc) if err! = nil {return errors.Wrap (err, "") } return nil} // uygulama yapılandırmalarıfunc loadConfig (dosya adı dizesi) (* config.AppConfig, hata) { ac, err: = config.ReadConfig (dosyaadı) eğer hata! = nil {return nil, errors.Wrap (err, "kapsayıcı oku")} return ac, nil}

3. "yapılandırmalar" alt paketi: YAML dosyalarından program yapılandırmalarını yüklemek ve bunları kapsayıcı kullanımı için "appConfig" yapısına kaydetmekle sorumludur.

4. "kaydedici" alt paketi: Bir logger arayüzü ve logger'a erişmek için bir "Log" değişkeni sağlayan tek bir "logger.go" dosyası vardır. Her dosya bağımlılık kayıtları gerektirdiğinden, döngüsel bağımlılıkları önlemek için ayrı bir pakete ihtiyaç duyar.

5. Son bölüm farklı türdendir Fabrika ).

Dahili katmanlaması, uygulama katmanı katmanlamasına uygundur. "Usecase" ve "dataservice" katmanları için "usecasefactory" ve "dataservicefactory" vardır. Diğer fabrika, temel veri işleme bağlantısını oluşturmaktan sorumlu olan "veri deposu fabrikası" dır. Veri sağlayıcı gRPC veya veri tabanının yanı sıra başka hizmet türleri olabileceğinden, "veri deposu" yerine "veri deposu" olarak adlandırılır. Günlük bileşeni (kaydedici) ayrıca kendi fabrikasına sahiptir.

Use Case Factory

"Kayıt" gibi her bir kullanım durumu için, arayüz "kullanım durumu" paketinde tanımlanır, ancak belirli tür "kullanım durumu" paketi altındaki "kayıt" alt paketinde tanımlanır. Ek olarak, kapsayıcı paketinde belirli kullanım durumu örneklerinin oluşturulmasından sorumlu ilgili bir fabrika vardır. "Kayıt" kullanım durumu için bu, "registrationFactory.go" dur. Kullanım durumları ile kullanım senaryosu fabrikaları arasındaki ilişki bire birdir. Kullanım senaryosu fabrikası, bu kullanım senaryosunun somut türünü oluşturmaktan ve diğer fabrikaları, beton türünün gerektirdiği bir yapıda üyeleri oluşturmaya çağırmaktan sorumludur. En alt seviyeye özgü türler, veritabanındaki verilere erişmek için kalıcılık katmanına iletilmesi gereken sql.DB'ler ve gRPC bağlantılarıdır.

Go jenerikleri destekliyorsa, farklı türlerde örnekler oluşturmak için genel bir fabrika oluşturabilirsiniz. Şimdi her kat için bir fabrika oluşturmalıyım. Diğer bir seçenek de, yansıtmayı kullanmaktır, ancak birçok sorunu var, bu yüzden kullanmadım.

"Kayıt" Kullanım Örneği Fabrikası:

Fabrika her çağrıldığında yeni bir tip inşa edecek. Aşağıda, belirli kod türlerini oluşturmak için "Kayıt (Kayıt)" kullanım durumu verilmiştir. Fabrika yöntemi modelinin tipik bir uygulamasıdır. Go'da fabrika yöntemi modelinin nasıl uygulanacağı hakkında daha fazla bilgi edinmek isterseniz, lütfen buraya bakın refer.

// Build, RegistrationUseCaseInterfacefunc (rf * RegistrationFactory) Build (c container.Container, appConfig * config.AppConfig, key string) (UseCaseInterface, hata) {uc: = appConfig .Case.Registrationudi, err: = buildUserData (c , uc.UserDataConfig) if err! = nil {return nil, errors.Wrap (err, "")} tdi, err: = buildTxData (c, uc.TxDataConfig) eğer err! = nil {return nil, errors.Wrap ( err, "")} ruc: = kayıt.RegistrationUseCase {UserDataInterface: udi, TxDataInterface: tdi} dönüş ruc, nil} func buildUserData (c container.Container, dc * config.DataConfig) (dataservice.UserDataInterface, error) (dsi, err: = dataservicefactory.GetDataServiceFb (dc.Code) .Build (c, dc) eğer err! = nil (return nil , errors.Wrap (err, "")} udi: = dsi. (dataservice.UserDataInterface) döndür udi, nil}

Veri deposu fabrikası:

"Kayıt" kullanım durumu, veri depolama fabrikası tarafından oluşturulan veritabanı bağlantısı aracılığıyla veritabanına erişim gerektirir. Tüm kod "datastorefactory" alt paketindedir. Veri depolama fabrikasının nasıl çalıştığını ayrıntılı olarak anlattım, lütfen Bağımlılık Enjeksiyonu makalesine bakın.

Veri depolama fabrikasının mevcut uygulaması, iki veritabanını ve bir mikro hizmeti, MySql ve CouchDB'yi ve gRPC önbellek hizmetini destekler; her uygulamanın kendi fabrika dosyası vardır. Yeni bir veritabanı tanıtılırsa, yalnızca yeni bir fabrika dosyası eklemeniz ve aşağıdaki kodda "dsFbMap" içine bir giriş eklemeniz gerekir.

// "Veritabanı kodunu" "veritabanı arabirim oluşturucu" ile eşlemek için // Concreate oluşturucu ilgili fabrika dosyasındadır. Örneğin, "sqlFactory" "sqlFactory" .govar dsFbMap = mapdsFbInterface {config.SQLDB: sqlFactory {}, config .COUCHDB: couchdbFactory {}, config.CACHE_GRPC: cacheGrpcFactory {},} // DataStoreInterface, Build yöntemi DataStoreInterface arayüzü için dönüş türünü belirtmek için bir işaretçi görevi görür {} // Fabrika yöntemi modeli için oluşturucu arabirimi // Her fabrikanın Derleme yöntemi dsFbInterface arabirimini uygulaması gerekir {Build (container.Container, * config.DataStoreConfig) (DataStoreInterface, error)} // GetDataStoreFb, factoryBuilderMapfunc için erişimcilerdir GetDataStoreFb (anahtar dizesi) dsFbInterface {return dsFbMap}

Aşağıda, yukarıdaki kodda tanımlanan "dsFbInterface" i uygulayan MySql veritabanı fabrikasının kodu verilmiştir. MySql veritabanına bir bağlantı oluşturur.

Konteynerin içinde, veri depolama fabrikası tarafından oluşturulan bağlantılar (DB veya gRPC bağlantıları gibi) için önbellek olarak kullanılan bir kayıt defteri vardır ve uygulama boyunca bir kez oluşturulurlar. İhtiyaç duyduğunuzda, önce kayıt defterinden almanız gerekir, yoksa yeni bir tane oluşturmanız ve kayıt defterine koymanız gerekir. Aşağıda "Yapı" kodu verilmiştir.

// sqlFactory, Build methodtype sqlFactory struct için alıcıdır {} // SQL databasefunc için Build yöntemini uygula (sf * sqlFactory) Build (c container.Container, dsc * config.DataStoreConfig) (DataStoreInterface, error) {key: = dsc.Code // zaten konteyner içindeyse, returnif değeri, bulunan: = c.Get (anahtar); bulunan {sdb: = değer. (* sql.DB) sdt: = databasehandler.SqlDBTx {DB: sdb} logger.Log.Debug ("anahtar için kapsayıcıda db bulundu:", anahtar) sdt döndür, nil} db, err: = sql.Open (dsc.DriverName, dsc.UrlAddress) if err! = nil {return nil, errors.Wrap (err, "")} // bağlantıyı kontrol eterr = db.Pingif err! = nil { nil dönüş, hatalar.Wrap (hata, "")} dt: = veri tutucu.SqlDBTx {DB: db} c.Put (anahtar, db) dönüş dt, nil }

Grpc Fabrikası:

"ListUser" kullanım durumu için, gRPC mikro hizmetini (önbellek hizmeti) çağırması gerekir ve onu oluşturan fabrika "cacheFactory.go" dur. Şu anda, veri hizmetlerine olan tüm bağlantılar veri depolama fabrikası tarafından oluşturulmaktadır. Aşağıdaki gRPC fabrikasının kodudur. "Build" yöntemi "SqlFactory" yöntemine çok benzer.

// DataStoreInterface, Build yöntemi DataStoreInterface arayüzü için dönüş türünü belirtmek için bir işaretçi görevi görür {} // cacheGrpcFactory, Derleme yöntemi cacheGrpcFactory yapısı için boş bir alıcıdır {} func (cgf * cacheGrpcFactory) Build (c container.Container, dsc * config.DataStoreConfig) (DataStoreInterface, error) (key: = dsc.Code // zaten kapsayıcıdaysa, returnif değeri, bulunan: = c.Get ( key); bulundu {dönüş değeri. (* grpc.ClientConn), nil} // haritada yok, onelogger.Log.Debug oluşturulması gerekiyor ("cacheGrpc anahtarını bulamıyor =% v yeni bir tane oluşturmalı \ n ", anahtar) conn, err: = grpc.Dial (dsc.UrlAddress, grpc.WithInsecure) if err! = nil {return nil, errors.Wrap (err, "")} c.Put (key, conn) return conn, err}

Kaydedici fabrikası:

Logger, "loggerfactory" adlı kendi alt paketine sahiptir ve yapısı "datastorefactory" alt paketine çok benzer. "LogFactory.go", kaydedici fabrika oluşturucu arabirimini (oluşturucu arabirimi) ve eşlemeyi (harita) tanımlar. Her bir kaydedicinin kendi fabrika dosyası vardır. Aşağıda, günlük fabrikasının kodu verilmiştir:

// günlükçü kodunu günlükçü oluşturucuya eşlemek için günlükçü eşlemesi var logfactoryBuilderMap = maplogFbInterface {config.ZAP: ZapFactory {}, config.LOGRUS: LogrusFactory {},} // günlükçü fabrika türü için arayüz logFbInterface arayüzü {Build (* config.LogConfig) error} // factoryBuilderMapfunc için erişimciler GetLogFactoryBuilder (anahtar dizesi) logFbInterface {return logfactoryBuilderMap}

Aşağıdaki ZAP fabrikasının kodudur. Bir veri depolama fabrikasına benzer. Tek bir fark var. Kayıt cihazı oluşturma işlevi yalnızca bir kez çağrıldığından, kayıt formu gerekmez.

// zap fabrika türü ZapFactory yapısı için alıcı {} // zap loggerfunc (mf * ZapFactory) Build (lc * config.LogConfig) hatası {err: = zap.RegisterLog (* lc) if err! = nil {return errors.Wrap (err, "")} return nil}

Yapılandırma dosyası

Yapılandırma dosyası, programın genel yapısını tam olarak anlamanıza olanak tanır:

Yukarıdaki görüntü dosyanın ilk yarısını göstermektedir. İlk bölüm desteklediği veritabanı yapılandırması; ikinci bölüm gRPC ile mikro hizmet; üçüncü bölüm desteklediği günlükçü; dördüncü bölüm çalışma zamanında bu program tarafından kullanılan günlük kaydedicidir.

Aşağıdaki resim dosyanın ikinci yarısını göstermektedir. Uygulamanın tüm kullanım durumlarını ve her kullanım durumu için gereken veri hizmetlerini listeler.

Yapılandırma dosyasına hangi veriler kaydedilmelidir?

Farklı bileşenlerin farklı yapılandırma öğeleri vardır ve bazı bileşenlerin kaydedici gibi birçok yapılandırma öğesi olabilir. Yapılandırma dosyasındaki tüm yapılandırma öğelerini kaydetmemize gerek yoktur, bu da onu yönetmek için çok büyük hale getirebilir. Genellikle yalnızca çalışma zamanında değiştirilmesi gereken seçenekleri veya farklı ortamlarda farklı değerlere sahip olabilecek seçenekleri (dev, prod, qa) kaydetmemiz gerekir.

Tasarım nasıl gelişti?

Görünüşe göre konteyner çantasında çok fazla şey var. Asıl soru hepsine ihtiyacımız var mı? Tüm özelliklere ihtiyacınız yoksa, kesinlikle basitleştirebiliriz. Oluşturmaya başladığımda çok basitti, özellikler eklemeye devam ettim ve sonunda giderek daha karmaşık hale geldi.

Başlangıçta, belirli türler oluşturmak, günlüğe kaydetme, yapılandırma dosyası yok ve kayıt defteri oluşturmak için fabrika yöntemi modelini kullanmak istedim.

Kullanım senaryoları ve veri depolama fabrikaları ile başladım. Başlangıçta, her kullanım durumu için ideal olmayan yeni bir veritabanı bağlantısı oluşturulur. Bu nedenle, yalnızca bir kez oluşturulmalarını sağlamak için tüm bağlantıları önbelleğe almak için bir kayıt defteri ekledim.

Sonra buldum (buradan biraz ilham aldım), merkezi yönetim için tüm yapılandırma bilgilerini tek bir dosyaya koymanın iyi bir fikir olduğunu gördüm, böylece kodu değiştirmeden değişiklikler yapabilirim.

Bir YAML dosyası (appConfig.yaml) ve "appConfig.go" oluşturarak dosyanın içeriğini uygulama yapılandırma yapısına (struct) - "appConfig" yükleyip fabrika kurucusuna ilettim. "" "prod", "dev", "test" vb. olabilir. Yapılandırma dosyası yalnızca bir kez yüklenir. Şu anda, herhangi bir üçüncü taraf kitaplığı kullanmıyor, ancak gelecekte Vipe'ye geçmek istiyorum çünkü program yapılandırmasının yapılandırma sunucusundan dinamik olarak yeniden yüklenmesini destekleyebiliyor. Vipe'a geçmek için sadece bir "appConfig.go" dosyasını değiştirmem gerekiyor.

Günlük kaydı için, tüm program için yalnızca bir günlük kaydı örneği istiyorum, böylece tüm program için aynı günlük yapılandırmasını ayarlayabilirim. Konteynerin içinde bir kayıt paketi oluşturdum. Ayrıca hangisinin en iyisi olduğunu belirlemek için farklı günlük kaydı kitaplıkları denedim ve ardından gelecekte yeni kaydediciler eklemeyi kolaylaştırmak için bir günlük kaydı fabrikası oluşturdum. Daha fazla bilgi için, lütfen Günlük Yönetimi okuyun.

Tam kaynak program bağlantısı Github : https://github.com/jfeng45/servicetmpl

dizin:

ozzo-doğrulama

Go dili için YAML desteği

Golang Fabrikası Yöntemi

Temiz Mimari ile Mikro Hizmete Geçin: Bağımlılık Enjeksiyonu

Golang projelerinde paylaşılan kaynakları (veritabanları, yapılandırma vb.) Nasıl aktarırım?

engerek

Temiz Mimari ile Mikro Hizmete Geçin: Uygulama Günlüğü

Terimleri yığmayın, yapıları listelemeyin, otoriteye inanmayın, popüler eğilimleri körü körüne takip etmeyin ve bağımsız düşüncede ısrar etmeyin!

Orijinal bağlantı:

https://blog.csdn.net/weixin_38748858/article/details/103914642

Bugünün faydaları

Büyük kahve ile tanışın

CSDN tarafından teknik insanlar için oluşturulan yeni üst düzey diyalog sütunu "Büyük Kahve Geliyor" geliyor!

CSDN'nin kurucusu ve başkanı ve Geekbang Venture Capital'in kurucu ortağı Jiang Tao, Jingdong Group Teknoloji Başkan Yardımcısı, IEEE Üyesi, Jingdong Yapay Zeka Araştırma Enstitüsü Başkan Yardımcısı ve Derin Öğrenme ve Konuşma ve Dil Laboratuvarı başkanı He Xiaodong ile el ele verdi. Teknoloji CTO'su Hu Yichuan, Çin'de yapay zeka uygulamalarının ilk yılında geliştiricilerin ve işletmelerin gidişatından ve gelişim yönünden bahsetti!

Sabah Okuma Henan Eyaleti, Yuanyang İlçesi, Yuanxing Alt Bölge Ofisi'nden sorumlu kişi özür diliyor: sorumlu kişi soruşturmayı askıya aldı
önceki
Sadece kullan! Python her gün düzenli olarak bir aşk cümlesi gönderiyor | Güç Projesi
Sonraki
Jiang Fan, Ali ortağı olarak çıkarıldı; Li Guoqing resmi mührü çaldığını reddetti; MIUI 12 yayınlandı | Geek Manşet
Hong Kong Bilim ve Teknoloji Üniversitesi'nden akademisyen Zheng Guangting, AI'nın en son uygulamalarını ve uygulamalarını tartışarak geleceği sordu.
Poster Çin'in yeni taç pnömonisi salgınına karşı mücadeledeki uygulaması
Benimle görüşmeci arasında işletim sistemi hakkında bir oyun | The Force Project
Toplamak! MySQL röportajının ustalaşması gereken 8 bilgi noktası
İlk yerli sunucusuz veritabanı burada ve teknik mimari ortaya çıkıyor
Apple, iPhone e-posta güvenlik açığına yanıt veriyor; GitHub, arka arkaya 3 gün ciddi kesinti süresiyle patladı; Tencent açık kaynak Transformer çıkarım hızlandırma aracı | Geek Headlines
Piyasa İşlemi Tek Bölge Gücü! Suzhou'da Nisan ayının dördüncü haftasında 1.493 set konut işlemi% 1,50 arttı
Tayvan ordusunun enfekte filosu başka yerleri ziyaret etti mi? Tsai Ing-wen: Yan Defa Yok: Evet
İnsanları kurtarmak için aşağı koştu ve dizleri morarıncaya kadar diz çöktü.Netizenler, kimliğini öğrendikten sonra övdü ve haraç ödedi ...
Kırmızı Ağ Bin Ekran Ağı, sizi 2020 Hunan (Bahar) Kırsal Kültür Turizmi Festivali'ne katılmanız için "Anhua ile Tanışın" davet ediyor
"Salgın" ve "kötü" test sorularına nasıl cevap verilir? Genel Sekreter Xi Jinping rehberlik etti
To Top