成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Openresty的開(kāi)發(fā)閉環(huán)初探

ruicbAndroid / 947人閱讀

摘要:多返回值開(kāi)始變得越來(lái)越與眾不同了允許函數(shù)返回多個(gè)結(jié)果。這種情況函數(shù)沒(méi)有足夠的返回值時(shí)也會(huì)用來(lái)補(bǔ)充。中的索引習(xí)慣以開(kāi)始。

為什么值得入手?

Nginx作為現(xiàn)在使用最廣泛的高性能后端服務(wù)器,Openresty為之提供了動(dòng)態(tài)預(yù)言的靈活,當(dāng)性能與靈活走在了一起,無(wú)疑對(duì)于被之前陷于臃腫架構(gòu),苦于提升性能的工程師來(lái)說(shuō)是重大的利好消息,本文就是在這種背景下,將初入這一未知的領(lǐng)域之后的一些經(jīng)驗(yàn)與大家分享一下,若有失言之處,歡迎指教。

安裝

現(xiàn)在除了能在 Download里面下載源碼來(lái)自己編譯安裝,現(xiàn)在連預(yù)編譯好的包都有了, 安裝也就分分鐘的事了。

hello world

/path/to/nginx.conf, conftent_by_lua_file里面的路徑請(qǐng)根據(jù)lua_package_path調(diào)整一下。

location / {
    content_by_lua_file ../luablib/hello_world.lua;
}

/path/to/openresty/lualib/hello_world.lua

ngx.say("Hello World")

訪問(wèn)一下, Hello World~.

HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: application/octet-stream
Date: Wed, 11 Jan 2017 07:52:15 GMT
Server: openresty/1.11.2.2
Transfer-Encoding: chunked

Hello World

基本上早期的Openresty相關(guān)的開(kāi)發(fā)的路數(shù)也就大抵如此了, 將lua庫(kù)發(fā)布到lualib之下,將對(duì)應(yīng)的nginx的配置文件發(fā)布到nginx/conf底下,然后reload已有的Openresty進(jìn)程(少數(shù)需要清空Openresty shared_dict數(shù)據(jù)的情況需要重啟), 如果是測(cè)試環(huán)境的話,那更是簡(jiǎn)單了,在http段將lua_code_cache設(shè)為off, Openresty不會(huì)緩存lua腳本,每次執(zhí)行都會(huì)去磁盤(pán)上讀取lua腳本文件的內(nèi)容,發(fā)布之后就可以直接看效果了(當(dāng)然如果配置文件修改了,reload是免不了了),是不是找到一點(diǎn)當(dāng)初apache寫(xiě)php的感覺(jué)呢:)

開(kāi)發(fā)語(yǔ)言Lua的大致介紹

環(huán)境搭建完畢之后,接下來(lái)就是各種試錯(cuò)了,關(guān)于Lua的介紹,網(wǎng)上的資料比如:Openresty最佳實(shí)踐(版本比較多,這里就不放了)。 寫(xiě)的都會(huì)比較詳細(xì),本文就不在這里過(guò)多解釋了,只展示部分基礎(chǔ)的Lua的模樣。下面對(duì)lua一些個(gè)性有趣的地方做一下分享,可能不會(huì)涉及到lua語(yǔ)言比較全面或者細(xì)節(jié)的一些部分,作為補(bǔ)充,讀者可以翻閱官方的<>。

-- 單行注釋以兩個(gè)連字符開(kāi)頭 

--[[ 
     多行注釋
--]]

-- 變量賦值

num = 13  -- 所有的數(shù)字都是雙精度浮點(diǎn)型。

s = "單引號(hào)字符串"
t = "也可以用雙引號(hào)" 
u = [[ 多行的字符串
       ]] 

-- 控制流程,和python最明顯的差別可能就是冒號(hào)變成了do, 最后還得數(shù)end的對(duì)應(yīng)
-- while
while n < 10 do 
  n = n + 1  -- 不支持 ++ 或 += 運(yùn)算符。 
end 

-- for
for i = 0, 9 do
  print(i)
end

-- if語(yǔ)句:
f n == 0 then
  print("no hits")
elseif n == 1 then
  print("one hit")
else
  print(n .. " hits")
end

--只有nil和false為假; 0和 ""均為真! 
if not aBoolValue then print("false") end 

-- 循環(huán)的另一種結(jié)構(gòu): 
repeat 
  print("the way of the future") 
  num = num - 1 
until num == 0 

-- 函數(shù)定義:
function add(x, y)
  return x + y
end

-- table 用作鍵值對(duì)
t = {key1 = "value1", key2 = false} 

print(t.key1)  -- 打印 "value1". 

-- 使用任何非nil的值作為key: 
u = {["@!#"] = "qbert", [{}] = 1729, [6.28] = "tau"} 
print(u[6.28])  -- 打印 "tau" 

-- table用作列表、數(shù)組
v = {"value1", "value2", 1.21, "gigawatts"} 
for i = 1, #v do  -- #v 是列表的大小
  print(v[i])
end

-- 元表
f1 = {a = 1, b = 2}  -- 表示一個(gè)分?jǐn)?shù) a/b. 
f2 = {a = 2, b = 3} 

-- 這會(huì)失?。?-- s = f1 + f2 

metafraction = {} 
function metafraction.__add(f1, f2) 
  local sum = {} 
  sum.b = f1.b * f2.b 
  sum.a = f1.a * f2.b + f2.a * f1.b 
  return sum
end

setmetatable(f1, metafraction) 
setmetatable(f2, metafraction) 

s = f1 + f2  -- 調(diào)用在f1的元表上的__add(f1, f2) 方法 

-- __index、__add等的值,被稱為元方法。 
-- 這里是一個(gè)table元方法的清單: 

-- __add(a, b)                     for a + b 
-- __sub(a, b)                     for a - b 
-- __mul(a, b)                     for a * b 
-- __div(a, b)                     for a / b 
-- __mod(a, b)                     for a % b 
-- __pow(a, b)                     for a ^ b 
-- __unm(a)                        for -a 
-- __concat(a, b)                  for a .. b 
-- __len(a)                        for #a 
-- __eq(a, b)                      for a == b 
-- __lt(a, b)                      for a < b 
-- __le(a, b)                      for a <= b 
-- __index(a, b)    for a.b 
-- __newindex(a, b, c)             for a.b = c 
-- __call(a, ...)                  for a(...) 

以上參考了
learn lua in y minute ,做了適當(dāng)?shù)牟眉魜?lái)做說(shuō)明。

Lua語(yǔ)言個(gè)性的一面 第一道墻: 打印table

作為lua里面唯一標(biāo)準(zhǔn)的數(shù)據(jù)結(jié)構(gòu), 直接打印居然只有一個(gè)id狀的東西,這里說(shuō)這一點(diǎn)沒(méi)有抱怨的意思,只是讓讀者做好倒騰的心理準(zhǔn)備,畢竟倒騰一個(gè)簡(jiǎn)潔語(yǔ)言終歸是有代價(jià)的,了解決定背后的原因,有時(shí)候比現(xiàn)成的一步到位的現(xiàn)成方案這也是倒騰的另一面好處吧,這里給出社區(qū)里面的討論

舉個(gè)例子: lua里面一般使用#table來(lái)獲取table的長(zhǎng)度,究其原因,lua對(duì)于未定義的變量、table的鍵,總是返回nil,而不像python里面肯定是拋出異常, 所以#來(lái)計(jì)算table長(zhǎng)度的時(shí)候只會(huì)遍歷到第一個(gè)值為nil的地方,畢竟他不能一直嘗試下去,這時(shí)候就需要使用table.maxn的方式來(lái)獲取了。

Good or Bad? 自動(dòng)類型轉(zhuǎn)換

如果你在python里面去把一個(gè)字符串和數(shù)字相加,python必定以異?;貞?yīng)。

>>> "a" + 1
Traceback (most recent call last):
  File "", line 1, in 
TypeError: cannot concatenate "str" and "int" objects

但是Lua覺(jué)得他能搞定。

> = "20" + 10
30

如果你覺(jué)得Lua選擇轉(zhuǎn)換加號(hào)操作符的操作數(shù)成數(shù)字類型去進(jìn)行求值顯得不可思議的,下面這種情況下,這種轉(zhuǎn)換又貌似是可以有點(diǎn)用的了,print("hello" .. 123),這時(shí)你不用手動(dòng)去將所有參數(shù)手工轉(zhuǎn)換成字符串類型。尚沒(méi)有定論說(shuō)這項(xiàng)特性就是一無(wú)是處,但是這種依賴語(yǔ)言本身不明顯的特性的代碼筆者是不希望在項(xiàng)目里面去踩雷的。

多返回值

Lua開(kāi)始變得越來(lái)越與眾不同了:允許函數(shù)返回多個(gè)結(jié)果。

function foo0() end --無(wú)返回值
function foo1() return "a" end -- 返回一個(gè)結(jié)果
function foo2() return "a","b" end -- 返回兩個(gè)結(jié)果
-- 多重賦值時(shí), 函數(shù)調(diào)用是最后一個(gè)表達(dá)式時(shí)
-- 保留盡可能多的返回值
x, y = foo2()     -- x="a", y="b"
x = foo2()        -- x="a", "b"被丟棄
x,y,z = 10,foo2()    -- x=10, y="a", z="b"

-- 如果多重賦值時(shí),函數(shù)調(diào)用不是最后一個(gè)表達(dá)式時(shí)
-- 只產(chǎn)生一個(gè)值
x, y = foo2(),20   -- x="a", y=20   
x,y = foo0(), 20, 30 -- x=nil, y= 20,30被丟棄,這種情況當(dāng)函數(shù)沒(méi)有返回值時(shí),會(huì)用nil來(lái)補(bǔ)充。

x,y,z = foo2() -- x="a", y="b", z=nil, 這種情況函數(shù)沒(méi)有足夠的返回值時(shí)也會(huì)用nil來(lái)補(bǔ)充。

-- 同樣在函數(shù)調(diào)用、table聲明中 函數(shù)調(diào)用作為最后的表達(dá)式,都會(huì)竟可能多的填充返回值,如果不是最后,則只返回一個(gè)
print(foo2(), 1)    --> a  1
print(1, foo2())    --> 1  a  b
t = {foo2(), 1}     --> {"a", 1}
t = {1, foo2()}     --> {1, "a", "b"}

-- 阻止這種參數(shù)順序搞事:
print(1, (foo2())) -- 1 a 加一層括號(hào),強(qiáng)制只返回一個(gè)值
真?zhèn)€性: 模式匹配

簡(jiǎn)潔的Lua容不下行數(shù)比自己實(shí)現(xiàn)語(yǔ)言行數(shù)還多的正則表達(dá)式實(shí)現(xiàn)(無(wú)論是POSIX, 還是Perl正則表達(dá)式),于是乎有了獨(dú)樹(shù)一幟的模式與匹配,下面只用模式匹配來(lái)做URL解碼、編碼功能實(shí)現(xiàn)的演示。

-- 解碼
function unescape(s)
  s = string.gsub(s, "+", " ")
  s = string.gsub(s, "%%(%x%x)", function (h)
        return string.char(tonumber(h, 16))
      end)
  return s  
end

print(unescape("a%2Bb+%3D+c")) ---> a+b =c

cgi = {}
function decode(s)
  for name,value in string.gmatch(s, "([^&=]+)=([^&=]+)") do
    name = unescape(name)
    value = unescape(value)
    cgi[name] = value
  end
end

-- 編碼

function escape(s)
  s = string.gsub(s, "[&=+%%%c]", function(c)
      return string.format("%%%02X", string.byte(c))
    end)
  s = string.gsub(s, " ", "+")
  return s
end  

function encode(t)
  local b = {}
  for k,v in pairs(t) do
    b[#b+1] = (escape(k) .. "=" .. escape(v))
  end
  return table.concat(b,"&")
end

模式匹配實(shí)現(xiàn)的功能是足夠強(qiáng)大,但是工程上是否值得投入,還值得商榷,沒(méi)有通用性,只此lua一家用,雖然正則表達(dá)式也是不好調(diào)試,但是至少知道了解的人多,可能到最后筆者也不會(huì)多深入lua的模式匹配,但是如此單純?yōu)榱藴p少代碼而放棄正則表達(dá)式現(xiàn)成的庫(kù),自己又玩了一套,這也是沒(méi)誰(shuí)了。

與c的天然親密

一言不合,就拿c寫(xiě)一個(gè)庫(kù)給lua用,由此可見(jiàn)兩門(mén)語(yǔ)言是多么哥兩好了,如果舉個(gè)例子的話就是lua5.1里面的位操作符,luajit就是這樣提供的解決方案, Lua Bit Operations Module, 有興趣的讀者可以下載源碼看一下,完全就是用lua的c api包裝了c里面的位操作符出來(lái)用,除了加了些限制的話(ex.位移出來(lái)的必然是32位有符)。lua除了數(shù)據(jù)結(jié)構(gòu)上面的過(guò)于簡(jiǎn)潔外,其他的控制結(jié)構(gòu)、操作符這些語(yǔ)言特性基本該有的都有了,唯獨(dú)缺了位操作符,5.1為什么當(dāng)時(shí)選擇了不實(shí)現(xiàn)位操作符呢?有知道出處或者原因的讀者歡迎留言告知。(順帶一提,lua5.2里面有官方的bit32庫(kù)可以用,lua5.3已經(jīng)補(bǔ)上了位操作符,另外Openresty在lua版本的選擇上是選擇停留在5.1,這點(diǎn)在github的Issue里面有回答過(guò),且沒(méi)有升級(jí)的打算)

只有nil、false為布爾假。

lua中的索引習(xí)慣以1開(kāi)始。

沒(méi)有整型,所有數(shù)字都是浮點(diǎn)數(shù)。

當(dāng)函數(shù)的參數(shù)是單引號(hào)或者雙引號(hào)的字符串或者table定義的時(shí)候,可以省略外面的(), 所以require "cookie"并不是代表require是個(gè)關(guān)鍵字。

table[index] 等價(jià)于 table [index]

構(gòu)建公司層面完整的Openresty生態(tài) 開(kāi)發(fā)助手:成長(zhǎng)中的resty命令

習(xí)慣了動(dòng)態(tài)語(yǔ)言的解釋器的立即反饋,哪怕是熟悉lua的同學(xué),初入Openresty的時(shí)候似乎又想起了編譯->執(zhí)行->修改的無(wú)限循環(huán)的記憶,因?yàn)槊看味夹枰薷呐渲梦募?、reload、測(cè)試再如此重復(fù)個(gè)幾次才能寫(xiě)對(duì)一段函數(shù),resty命令無(wú)疑期待,筆者也希望resty命令能夠更加完善、易用。

另外提一個(gè)小遺憾,現(xiàn)在resty命令不能玩Openresty里面的shared_dict共享內(nèi)存, 這可能跟目前resty使用的nginx配置的模板是固定有關(guān)吧。

環(huán)境:可能不再需要重新編譯Nginx

有過(guò)Nginx維護(hù)開(kāi)發(fā)經(jīng)驗(yàn)的同學(xué)可能都熟悉這么一個(gè)過(guò)程,因?yàn)槎喟霑?huì)做業(yè)務(wù)的拆分,除了小公司外,基本都不會(huì)把一個(gè)Nginx的所有可選模塊都編譯進(jìn)去,每次有新的Nginx相關(guān)的功能的增減,都免不了重新編譯,重新部署上線,Openresty是基于Nginx的,如果是新增Nginx本身的功能,重新編譯增加功能沒(méi)什么好說(shuō)的,如何優(yōu)雅的更新Nginx服務(wù)進(jìn)程,Nginx有提供方案、各家也有各家的服務(wù)可靠性要求,具體怎么辦這里就不贅述了。

發(fā)布部署

Openresty本身的發(fā)布部署跟Nginx本身沒(méi)有太大的不同,Openresty本身的發(fā)布部署官方也推出了linux平臺(tái)的預(yù)編譯好的包,在這樣的基礎(chǔ)上構(gòu)建環(huán)境就更加便捷,環(huán)境之上,首先是lua腳本和nginx配置文件的發(fā)布,在版本管理之下,加上自動(dòng)構(gòu)建的發(fā)布平臺(tái),Openresty的應(yīng)用分分鐘就可以上線了:),這個(gè)流程本身無(wú)關(guān)Openresty,但是簡(jiǎn)而言之一句話,當(dāng)重復(fù)性的東西自動(dòng)化之后,我們才有精力去解決更有趣的問(wèn)題,不是么?

第三方庫(kù)的安裝、管理

以前: 自己找個(gè)第三方庫(kù)編譯之后扔到Openresty的lualib目錄,luajit是否兼容、是否lua5.1兼容都得自己來(lái)測(cè)試一遍。

之前: 對(duì)于解決前一個(gè)問(wèn)題,Openresty是通過(guò)給出lua里面Luarocks的安裝使用來(lái)解決的,但是這種方式不能解決上面所說(shuō)的第二個(gè)問(wèn)題,所以現(xiàn)在這種方式已經(jīng)不推薦使用了,下面貼一下官網(wǎng)的說(shuō)明,只做內(nèi)容收集、展示用, 最新的具體說(shuō)明參見(jiàn)using luarocks。

wget http://luarocks.org/releases/luarocks-2.0.13.tar.gz
tar -xzvf luarocks-2.0.13.tar.gz
cd luarocks-2.0.13/
./configure --prefix=/usr/local/openresty/luajit 
    --with-lua=/usr/local/openresty/luajit/ 
    --lua-suffix=jit 
    --with-lua-include=/usr/local/openresty/luajit/include/luajit-2.1
make
sudo make install

安裝第三方庫(kù)示例: sudo /usr/local/openresty/luajit/luarocks install md5。

現(xiàn)在: Openresty提供了解決這兩個(gè)問(wèn)題的完整方案,自己的包管理的規(guī)范和倉(cāng)庫(kù)opm。

詳細(xì)的標(biāo)準(zhǔn)說(shuō)明, 請(qǐng)移步: https://github.com/openresty/... 這里就不多做介紹了,關(guān)于第三方庫(kù)的質(zhì)量,Openresty官網(wǎng)上也有了專門(mén)的QA頁(yè)面,至少保證了第三方庫(kù)一些實(shí)現(xiàn)的下限,不像python里面安裝某些第三方包,比如aerospike的, 里面安裝python客戶端,每次要去網(wǎng)上拉個(gè)c的客戶端下來(lái)之類的稀奇古怪的玩法,期待opm未來(lái)更加完善。

關(guān)于單元測(cè)試

關(guān)于自動(dòng)化測(cè)試的話,就筆者的試用經(jīng)驗(yàn)而言,感覺(jué)還不是特別的順手,官方提供的Test:Nginx工具已經(jīng)提供簡(jiǎn)潔強(qiáng)大的功能,但是如果作為T(mén)DD開(kāi)發(fā)中的測(cè)試驅(qū)動(dòng)的工具而言,筆者覺(jué)得報(bào)錯(cuò)信息的有效性上面可能是唯一讓人有點(diǎn)覺(jué)得有點(diǎn)捉雞的地方,尚不清楚是否是筆者用的有誤,一般Test:Nginx的報(bào)錯(cuò)多半無(wú)法幫助調(diào)試代碼,還是要走調(diào)試、修改的老路子。但是Test:Nginx的真正價(jià)值筆者覺(jué)得是講實(shí)例代碼和測(cè)試完美的結(jié)合,由此養(yǎng)成了看每個(gè)Openresty相關(guān)的項(xiàng)目代碼都必先閱讀里面的Test:Nginx的測(cè)試,當(dāng)然最多最豐富的還是Openresty本身的測(cè)試。

舉個(gè)實(shí)際的例子,在使用Test:Nginx之前,之前對(duì)于Nginx的日志輸出,一切的測(cè)試依據(jù),對(duì)于外面的運(yùn)行環(huán)境跑的測(cè)試只能通過(guò)http的請(qǐng)求和返回來(lái)做測(cè)試的判斷條件,這時(shí)候?qū)τ谝恍┣闆r就束手無(wú)策了, 比如處理某種錯(cuò)誤情況可能需要在log里面記錄一下,這種測(cè)試就無(wú)法保證,另外也有類似lua-resty-test這樣通過(guò)提供組件的方式來(lái)進(jìn)行,但是我們一旦接觸的了Test:Nginx的測(cè)試方法之后,這些就顯得相形見(jiàn)絀了,我們舉個(gè)實(shí)際的例子。

# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;

#worker_connections(1014);
#master_process_enabled(1);
#log_level("warn");

#repeat_each(2);

plan tests => repeat_each() * (blocks() * 3 + 0);

#no_diff();
no_long_string();
#master_on();
#workers(2);

run_tests();

__DATA__

=== TEST 1: lpush & lpop
--- http_config
    lua_shared_dict dogs 1m;
--- config
    location = /test {
        content_by_lua_block {
            local dogs = ngx.shared.dogs

            local len, err = dogs:lpush("foo", "bar")
            if len then
                ngx.say("push success")
            else
                ngx.say("push err: ", err)
            end

            local val, err = dogs:llen("foo")
            ngx.say(val, " ", err)

            local val, err = dogs:lpop("foo")
            ngx.say(val, " ", err)

            local val, err = dogs:llen("foo")
            ngx.say(val, " ", err)

            local val, err = dogs:lpop("foo")
            ngx.say(val, " ", err)
        }
    }
--- request
GET /test
--- response_body
push success
1 nil
bar nil
0 nil
nil nil
--- no_error_log
[error]

以上是隨便選取的lua-nginx-module的測(cè)試文件145-shdict-list.t中的一段做說(shuō)明,測(cè)試文件分為3個(gè)部分,__DATA__以上的部分編排測(cè)試如何運(yùn)行, __DATA__作為分隔符, __DATA__以下的是各個(gè)測(cè)試的說(shuō)明部分. 測(cè)試部分如果具體細(xì)分的話,一般由====TEST 1: name開(kāi)始到下一個(gè)測(cè)試的聲明;然后是配置nginx配置的http_config、config、...的部分;接著是模擬請(qǐng)求的部分,基本就是http請(qǐng)求報(bào)文的設(shè)定,功能不限于這里的request部分;最后是輸出部分,這時(shí)候不僅是http報(bào)文的body部分之類的http響應(yīng)、還有nginx的日志的輸出這樣的測(cè)試條件,對(duì)于這樣清晰可讀、還能順帶把使用例子寫(xiě)的清楚的單元測(cè)試的框架,pythoner真的難道不羨慕么?

關(guān)于調(diào)試、性能調(diào)優(yōu)

這一塊筆者還沒(méi)有深入研究過(guò),所以,這里就不多說(shuō)了,這里就做一下相關(guān)知識(shí)的鏈接歸納,方便大家整理資料吧。

lua語(yǔ)言本身提供的調(diào)試就比較簡(jiǎn)潔、加上Openresty是嵌入Nginx內(nèi)部的,這就更給排查工作帶來(lái)了困難。

官方的調(diào)試頁(yè)面

官方的性能調(diào)優(yōu)頁(yè)面

通過(guò)systemtap探查在線的Nginx work進(jìn)程

額外的工具庫(kù)stap++

工具火焰圖Flame Graphs的介紹

Linux Kernel Performance: Flame Graphs

反爬蟲(chóng)

作者 toyld 豈安科技搬運(yùn)代碼負(fù)責(zé)人
主導(dǎo)各處的挖坑工作,擅長(zhǎng)挖坑于悄然不息,負(fù)責(zé)生命不息,挖坑不止。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/39428.html

相關(guān)文章

  • 馬蜂窩火車(chē)票系統(tǒng)服務(wù)化改造初探

    摘要:為了幫助用戶更好地完成消費(fèi)決策閉環(huán),馬蜂窩上線了大交通業(yè)務(wù)。現(xiàn)在,用戶在馬蜂窩也可以完成購(gòu)買(mǎi)機(jī)票火車(chē)票等操作。第二階段架構(gòu)轉(zhuǎn)變及服務(wù)化初探從年開(kāi)始,整個(gè)大交通業(yè)務(wù)開(kāi)始從架構(gòu)向服務(wù)化演變。 交通方式是用戶旅行前要考慮的核心要素之一。為了幫助用戶更好地完成消費(fèi)決策閉環(huán),馬蜂窩上線了大交通業(yè)務(wù)?,F(xiàn)在,用戶在馬蜂窩也可以完成購(gòu)買(mǎi)機(jī)票、火車(chē)票等操作。 與大多數(shù)業(yè)務(wù)系統(tǒng)相同,我們一樣經(jīng)歷著從無(wú)到有...

    Raaabbit 評(píng)論0 收藏0
  • 馬蜂窩火車(chē)票系統(tǒng)服務(wù)化改造初探

    摘要:為了幫助用戶更好地完成消費(fèi)決策閉環(huán),馬蜂窩上線了大交通業(yè)務(wù)?,F(xiàn)在,用戶在馬蜂窩也可以完成購(gòu)買(mǎi)機(jī)票火車(chē)票等操作。第二階段架構(gòu)轉(zhuǎn)變及服務(wù)化初探從年開(kāi)始,整個(gè)大交通業(yè)務(wù)開(kāi)始從架構(gòu)向服務(wù)化演變。 交通方式是用戶旅行前要考慮的核心要素之一。為了幫助用戶更好地完成消費(fèi)決策閉環(huán),馬蜂窩上線了大交通業(yè)務(wù)。現(xiàn)在,用戶在馬蜂窩也可以完成購(gòu)買(mǎi)機(jī)票、火車(chē)票等操作。 與大多數(shù)業(yè)務(wù)系統(tǒng)相同,我們一樣經(jīng)歷著從無(wú)到有...

    doodlewind 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<